Skip to main content

Building in browser text search for Firebase with a Lean mindset

· 3 min read

Nowadays, search is a basic feature in a public online tool. It’s a commodity, a feature that you expect to be there. Can you imagine using a database manager and not being able to search through your records? What happens when you have 500 rows?

Text Search is not that easy at scale

Now, if you are familiar with our tech stack, particularly Firebase and Firestore, you would know that it’s not such an easy task. In the past versions of FireCMS, we recommended using Algolia as an external plugin. Or any other compatible solutions, since you are in charge of everything, as in any open source product.

But what happens when you need it in a SaaS formulation. Recently, we launched FireCMS Cloud. We still allow customers to host their own Google Cloud project resources, but the app used for managing the data is on our side. So, we are in charge of the CMS, you don’t need to worry about that. Okay, great. We help you manage the app, rolling updates, support, and everything else.

But, how can you build text search features for every project without indexing each one of your records? Well, there are many responses, from using an external platform, such as Algolia, having our own Elasticsearch cluster or if you want to be fancy, even using a Vector store, where you could have real semantic search.

Lean Solution

Okay, but that requires some work and we are not 100% sure that’s something all our customers want. In fact, we have very little feature requests regarding this feature. So, we decided to go for a Lean solution. Start with something small, but powerful enough to provide a solution meanwhile we think for a better solution. But still, something that can help us validate that this will be helpful.

So we decided to implement in-browser search. Storing a local cache in the browser. It’s not the best solution in the market, it’s probably a little slow for big collections. But it’s something that works right away. And solves the search for most of our customers.

And what’s the best thing? You can activate it right away in your FireCMS Cloud project. We just rolled it out for everyone.

text_search_dialog.png

Now, our customers from Botanica Madrid can find any exotic named plant, such as a Zamioculca.

botanica_search.png

Go try it and tell us what you think.

Conclusion

So, when your team is small, sometimes it's helpful to build and release fast. Test, measure, and check if the development effort may satisfy a problem your customers are having.

Anyway, if you need a hand setting up a project, you have any issue, or you need help building a feature, reach us out at hello@firecms.co.2023-09-19-openai_code_migration.md

Automated code migrations with OpenAI's GPT-4

· 6 min read

In the day-to-day world of development, activities such as refactoring and migrating code consume a significant amount of time. Tasks such as restructuring code packages, renaming variables, altering function signatures, among others, are often tedious and fraught with errors. These operations can be effectively automated with the assistance of artificial intelligence. This article explains how to use OpenAI's GPT-4 to automatically refactor and migrate code.

At FireCMS, a prime motivation for adopting this approach is the migration of code from the JavaScript CSS library emotion to the CSS framework tailwindcss. This article specifically covers how to automatically convert code from emotion to tailwindcss, but the approach can be generalized to automate migration among any pair of libraries.

emotion allows components to be styled using JavaScript and tailwindcss offers the use of CSS classes to style components. While emotion carries a runtime footprint, tailwindcss works on a build-time footprint. Consequently, switching from emotion to tailwindcss can substantially improve the performance of an application.

This article demonstrates the creation of a basic Node.js script to automate the above-mentioned process, thereby extending the approach to handle any code migration scenario.

Note that you can apply the same approach to any other code migration.

Identifying the Problem

  • Emotion defines styles utilizing the sx prop, as shown in the code snippet below, which presents a button with a red background:
import {Button} from "@mui/material";

const MyButton = () => {
return <Button sx={{backgroundColor: "red"}}>Click me</Button>
}
  • Contrarily, tailwindcss uses CSS classes to define styles, as shown in the following code snippet, which defines a similarly-styled button:
import {Button} from "@mui/material";

const MyButton = () => {
return <Button className="bg-red-500">Click me</Button>
}

The goal is to construct a script capable of automating the conversion of code from emotion to tailwindcss style definitions.

Automating Code Migration through AI

The Node.js script illustrated here traverses the source code's folder structure and replaces emotion styles with tailwindcss styles. This process involves identifying JSX ot TSX elements containing the sx prop and replacing them with their corresponding className prop.

Traversing the Code

Here's a simple function that recursively traverses the source code's folder structure, returning all file paths and their contents:

const getRecursiveFileReads = async (dir: string, onFileRead: (filePath: string, content: string) => void) => {
const files = await fs.readdir(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = await fs.stat(filePath);
if (stat.isDirectory()) {
getRecursiveFileReads(filePath, onFileRead);
continue;
}
const content = await fs.readFile(filePath, { encoding: "utf8" });
onFileRead(filePath, content);
}
}

Detecting Emotion Styles

To identify sx props within the file content, we use a regular expression as shown:

const sxRegexp = /(sx=\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})/g;

This regular expression matches the sx prop as well as its value and can identify the styles defined in sx as shown in the earlier sections.

Replacing Emotion Styles with Tailwindcss Styles

Now, let's employ a function to replace the sx prop with the className prop. GPT-4 from OpenAI will be utilised to generate the className prop value in response to the following prompt:

You are a tool which only purpose is converting sx props from the emotion library to tailwind classes.
If there is no obvious translation, use classes and styles. E.g:

sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100vh',
backgroundColor: 'red',
}}

converts to:

className="flex items-center justify-center w-full h-screen bg-red-500"

Return exclusively results in the form of 'className="..."' or 'style={{...}}'
since your output will be injected into a tsx file.

We are instructing GPT-4 to generate the className prop value. We are also instructing GPT-4 to return exclusively results in the form of className="..." or style={{...}} since our output will be injected into a tsx file.

Any other output from GPT-4 would result in invalid code.

We will use the OpenAI library to make the corresponding call:

import { Configuration, CreateChatCompletionRequest, OpenAIApi } from "openai";

export const openai = new OpenAIApi(new Configuration({
apiKey: "YOUR_API_KEY"
}));

async function getOpenAiReplacement(input: string) {
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [
{
role: "system",
content: systemInstructions
},
{
role: "user",
content: input
}
],
temperature: 0.7,
top_p: 1,
});
return completion.choices[0].message?.content;
}

Full script

Finally, having all the snippets together enables us to write the full script. Replace FOLDER with the path of the source code you want to migrate, and remember to add your OpenAI API key.

You can run this script with ts-node script.js. If you prefer a dry-run mode, just set dryRun to true.

The complete script is attached below:

import path from "path";
import * as fs from "fs/promises";

import { Configuration, CreateChatCompletionRequest, OpenAIApi } from "openai";

const FOLDER = "../src";

const openai = new OpenAI({
apiKey: "YOUR_API_KEY"
});

const dryRun = false;
const sxRegexp = /(sx=\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})/g;

const getRecursiveFileReads = async (dir: string, onFileRead: (filePath: string, content: string) => void) => {
const files = await fs.readdir(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = await fs.stat(filePath);
if (stat.isDirectory()) {
getRecursiveFileReads(filePath, onFileRead);
continue;
}
const content = await fs.readFile(filePath, { encoding: "utf8" });
onFileRead(filePath, content);
}
}

let count = 0;

getRecursiveFileReads(FOLDER,
async (filePath, content,) => {
if (content.includes("sx={")) {
let newContent = content;
let match;
while ((match = sxRegexp.exec(content)) !== null) {
const sxData = match[1];
console.log(sxData);
if (!dryRun) {
const replacement = await getOpenAiReplacement(sxData);
if (replacement) {
console.log(replacement);
newContent = newContent.replace(sxData, replacement);
}
}
}
fs.writeFile(filePath, newContent);
count++;
console.log("Processed files", count);
}
});


async function getOpenAiReplacement(input: string) {
const completionParams: CreateChatCompletionRequest = {
model: "gpt-4",
messages: [
{
role: "system",
content: systemInstructions
},
{
role: "user",
content: input
}
],
temperature: 0.7,
top_p: 1,
};

const completion = await openai.createChatCompletion(completionParams);
return completion.data.choices[0].message?.content;
}

const systemInstructions = `You are a tool which only purpose is converting sx props from the emotion library to tailwind classes.
If there is no obvious translation, use classes and styles. E.g:

sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100vh',
backgroundColor: 'red',
}}

converts to:

className="flex items-center justify-center w-full h-screen bg-red-500"

Return exclusively results in the form of 'className="..."' or 'style={{...}}'
since your output will be injected into a tsx file.`

Conclusion

This process has been successfully applied to the FireCMS codebase, resulting in a significant reduction in the runtime footprint of the application. It has helped us intensively in a very tedious task. Of course some manual work is still required, but a good part of the work is done.

Of course, you can think of ways of improving this script. For example, you could tell OpenAI your tailwind.config.js content, so it can generate the classes based on your configuration.

I hope you enjoyed this article and that it will help you in your next code migration!

Integrating ChatGPT into Existing CMS Systems - A Game Changer for Content Management

· 6 min read

pawel-czerwinski-C2tWWNKExfw-unsplash.jpg Content Management Systems (CMS) are widely used across various industries to create, edit, and manage digital content. These platforms have evolved with time, offering more advanced features, functionality, and integration options. One of the most recent and promising developments in this area is the integration of ChatGPT, a powerful AI language model, into existing CMS systems.

Imagine a world where content management is no longer a tedious, time-consuming process. A world where your CMS system can understand context, translate languages, and even generate content on its own. Sounds like a dream come true, right? Well, thanks to ChatGPT, this dream is quickly becoming a reality. In this article, we’ll explore how ChatGPT, the AI-powered language model, can revolutionize content management systems by swooping in like a superhero to save the day — and your content!

ChatGPT: A Brief Overview

ChatGPT, developed by OpenAI, is a cutting-edge AI language model that can generate human-like text based on the input provided. It leverages advanced machine learning algorithms and natural language processing capabilities to understand context, generate responses, and even translate languages. This technology has immense potential for integration into various digital platforms, including CMS systems.

codioful-formerly-gradienta-26WixHTutxc-unsplash.jpg

How ChatGPT Can Enhance CMS Systems

Picture ChatGPT as the superhero sidekick to your CMS. It’s here to help you tackle content management challenges and make your life easier. Let’s take a look at some of the extraordinary abilities it brings to the table:

1. Autofilling Fields ChatGPT can be used to autofill fields within a CMS, saving time and effort for content creators and editors. By analysing the context of a specific entry, the AI can generate relevant content, titles, descriptions, tags, or other metadata required by the system.

2. Completing Missing Data In some cases, CMS users might have incomplete data sets or face difficulty in finding the right information to fill specific fields. ChatGPT can analyze the available data and generate the missing information, ensuring a more comprehensive and accurate content record.

3. Translations With its advanced language processing capabilities, ChatGPT can provide translations for content within a CMS, allowing content creators to easily publish their work in multiple languages. This feature can help businesses reach a wider audience and improve global engagement.

4. Content Generation ChatGPT’s ability to generate human-like text can be used to create new content within a CMS. For example, it can generate blog posts, product descriptions, or other content types based on the user’s input, substantially reducing the time and effort required.

5. Content Optimisation ChatGPT can analyse existing content and suggest improvements to enhance readability, SEO, and user engagement. It can help identify and fix grammar, spelling, and punctuation issues, as well as optimize keyword usage, headings, and metadata to improve search engine rankings.

6. Content Personalisation By leveraging user data and analytics, ChatGPT can generate personalized content recommendations for individual users. This could include tailoring article suggestions, product recommendations, or other content based on user preferences, browsing history, and demographics, leading to a more engaging user experience.

7. Content Summarization ChatGPT can automatically generate concise summaries of articles, reports, or other long-form content within the CMS. This feature can help users quickly understand the main points of a piece of content without having to read the entire text, making it easier to browse and navigate the website.

8. Automated Content Curation ChatGPT can be used to automatically curate content for newsletters, roundups, or other compilation-style posts. By analyzing user preferences, topic relevance, and content popularity, ChatGPT can generate a list of suitable articles or pieces of content to be included in such compilations, saving time and effort for content creators and editors.

9. Comment Moderation Integrating ChatGPT with a CMS can help facilitate automated comment moderation. The AI can analyze user-generated comments for spam, inappropriate language, or other violations of community guidelines, and either flag or remove them automatically, ensuring a safe and welcoming environment for users.

10. FAQ Generation ChatGPT can assist in creating Frequently Asked Questions (FAQs) sections for websites by analyzing existing content and user queries. This feature can help businesses quickly address common concerns and questions from their audience and improve overall user experience.

11. Topic Research ChatGPT can be used to generate content ideas and topics for articles, blog posts, or other forms of content. By analyzing trends, user interests, and related content, the AI can suggest fresh and engaging topics for content creators to explore.

These are just a few examples of the many potential use cases for integrating ChatGPT with a CMS. As AI technology continues to evolve, the possibilities for enhancing content management and user experiences will only grow.

CMSs

FireCMS: Extracting Structured Data from ChatGPT Outputs

As impressive as ChatGPT’s capabilities are, it’s essential to ensure that its outputs can be effectively integrated into a CMS platform. FireCMS, an open-source CMS, demonstrates a successful approach to extracting structured data from ChatGPT outputs and adapting it to any given data entity structures.

FireCMS can be configured to communicate with ChatGPT, sending input queries and receiving generated content. By implementing custom parsers and data processing tools, FireCMS can extract the relevant information from ChatGPT’s outputs and adapt it to the required data structure. This process allows FireCMS to seamlessly integrate ChatGPT-generated content into its existing content management workflow.

The integration of FireCMS with OpenAI is completely free to try in your own project, no subscriptions required!

https://youtube.com/shorts/WIfHyvDRam0

Conclusion

The integration of ChatGPT into CMS systems has the potential to revolutionise content management, making it more efficient, accurate, and versatile. By autofilling fields, completing missing data, providing translations, and generating content, ChatGPT can streamline content creation and management processes while offering a higher degree of automation.

FireCMS showcases a successful approach to integrating ChatGPT into a CMS platform, setting the stage for other CMS systems to follow suit. As AI technology continues to advance, the potential for further improvements and innovations in content management is limitless.

Release of version 1.0.0

· 4 min read

Dark mode

FireCMS 1.0 is ready to ship! 🙌 abd why Firebase makes for an amazing developer experince

A few months have passed since we entered the beta period of FireCMS, our Firestore-based CMS built with developer experience in mind.

We have collected your feedback to add new features and quality of life improvements, fixed bugs, and merged your PRs (thank you!).

After reaching more than 500 stars on GitHub, and 100 forks, it is a good time to finally end the beta and release-candidate phases and ship version 1.0.0

Why Firebase and FireCMS

At Camberi, we have been developing web apps and mobile apps for a long time. We have used Firebase and Firestore as a backend and database in multiple projects.

Our experience overall has been great!

Firebase offers a very powerful backend out of the box, and allows to kickstart a project in no time. It provides SDKs for the most relevant platforms, such as web, iOS or Android (and more) and has some features that make it stand out, like real-time data synchronisation and its scalability.

If you need to start a new project and don't want to spend too many resources in the backend, Firebase is the way to go. But this doesn't mean you can't build complex apps with it!

If you are coming from a more traditional backend setup you will need to make a bit of a mind switch. You can extend the functionality of your backend using functions, and have triggers when the data in your database gets updated.

Also, you are not forced to connect your apps to Firestore and you can build have a REST API or use callable functions to have your backend logic.

And, even if you don't want to use any of the Firebase services, because you already have your auth and APIs in place, you can set up a Firebase with FireCMS project just to manage your content.

We built FireCMS out of necessity.

If you are coming from a SQL background you will need to get used to de-normalising your data and having limited querying capabilities

Where we are

For every Firebase project that we developed for a client we needed a way to manage their content, and provide a backend admin panel. So we built our own!

After more than 2 years of development, FireCMS has gone from a simple app that would let us produce some simple CRUD views over collections to a full-blown CMS that includes:

  • Detailed CRUD views for collections.
  • Super powerful data tables with inline editing, alla AirTable.
  • Awesome, performant and beautiful UI.
  • Form views with more than 20 different widgets, including advanced ones such as:
    • File uploads
    • Reference support for different collections
    • Date time
    • Enumerations
    • ...and many more!
  • Possibility to customise your own form fields and how the underlying data is rendered.
  • Possibility to build fields based on other values.
  • Subcollections support.
  • Virtualized views for performance.
  • Text search support.
  • Customisation the CMS based on the logged-in user.

FireCMS offer more customization options than any other alternative, such as Rowy or Flamelink. It even offers features that are not available in some well established CMS like WordPress or Strapi, like the inline editing.

The future

We keep on getting amazed on how you are finding innovative ways to use FireCMS and we want to make it easier for you to do so.

We are already working on version 2 of FireCMS and are improving on almost every aspect of it:

  • Forms layouts and performance.
  • Internal and external APIS
  • Reusability of internal components
  • Property builders at any level of your property tree, not just at the root.
  • Improved modularity and reusability of components

FireCMS enters the beta period

· 5 min read

Exciting times for our project!

After more than 60 releases, and numerous refinements of the internal components and APIs, we are ready to start the beta release of version 1.0.0 💃

We now consider that the code and the UX and UI are mature enough to create a beta release (though we have multiple instances of previous versions already in production!).

In the last months we've been focused on improving the CMS quality by doing a lot of internal restructuring that is also going to affect the public facing APIs.

A bit of background

We started building FireCMS out of necessity. We were working on several projects based on Firebase and in most of them we needed to develop some kind of backend admin panel/CMS. We took some of those tools we had built, and merged them into a single generic project that would support any database structure and data type. We needed to make sure that we would need to be able to customize many aspects of each implementation based on the necessity.

The outcome was a very good starting point to what would become FireCMS after many iterations and feature updates. One of the consequences of this approach was that the code was tightly coupled to Firebase, and you could find imports to Firebase code in most layers of the code.

The influence of Firebase

The original coupling to Firebase and specially the data structure of Firestore has influenced many aspects of this project. The way we create entities based on documents and collections and subcollections mimics the Firestore data structure. What seemed like a limitation has turned out to be an opportunity to think of a great UI.

At FireCMS we have a special passion for user experience and believe that internal admin tools don't always receive the love they deserve.

In this time, we have developed some high quality components such as the spreadsheet views of collections, or the side panel to edit entities and nested subcollections.

Where we are going

In the last year, we have seen developers integrate FireCMS in ways we had never imagined! We have tweaked the APIs to try to accommodate those requirements, but we have come to the conclusion that a bigger change was needed.

The result is a big rework of the internal APIs and components that improves re-usability and customisation.

We have also added a lot of minor performance tweaks as well as design tweaks and improvements, including a very awesome new dark mode!

If you are using FirebaseCMSApp (previously CMSApp), so FireCMS as a standalone app, you will need to update some APIs (see the Migrating from alpha versions).

But, but, but... If you need more customisation you can now completely override FirebaseCMSApp and reuse all its internal components. This means you now have control of the MUI theme (adapted to V5), the CMS routes (adapted to React Router 6), or how you display the different parts, such as the side dialogs, or add your own.

You are now free to integrate the new FireCMS component and reuse all the internal components, combine them with your own, build your own custom themes or custom backend implementations.

Separation of concerns

In the process of having a cleaner code, all the code related to Firebase has been isolated into 3 components, one for authentication, one for the data source and one for storage. These components are abstracted away behind their respective interfaces. This means you can replace any of those parts with your custom implementation!

We have three new types that abstract away the services provided by Firebase:

  • AuthDelegate, in charge of handling the auth operation such as login or sign out, and build the logged-in user.
  • DataSource, in charge of handling data operation (fetch, listen, save, delete).
  • StorageSource, in charge of dealing with file storage operations.

We provide implementation for using Firebase Auth, Firestore and Firebase Storage, assigned by default if you use FirebaseCMSApp.

This means that you are now able to use FireCMS with any backend, auth or storage solution. If you want to go this way, you can check an example implementation of FireCMS that uses the internal components instead of FirebaseCMSApp

How did it go?

If you have been using FireCMS with a custom backend, we would love to hear your feedback either in our Discord channel or directly at hello@firecms.co 😊

Code quality

We have done a huge internal refactor that affects pretty much every part of the CMS. We have now a much better separation of the internal packages. There is also a package named firebase_app which encapsulates an implementation of FireCMS that uses the Firebase services as backend.

All the code referring to Firebase can be found only in this internal package, and nowhere else. This means the core of FireCMS has been completely isolated from Firebase and is now much more maintainable and extendable.

We have got a lot of PRs and support from out users and would love to foster that participation going forward. A cleaner code will help everyone involved and allow for more and better features!

Big types refactor

· 4 min read

Types update

We have a big update in version 0.49.0 affecting the main types used in the CMS.

The signature of EntitySchema<Key extends string = string> has changed to EntitySchema<M> where M is your model type like:

import { buildSchema } from "@camberi/firecms";

type Product = {
name: string;
price:number;
}

const productSchema = buildSchema<Product>({
// ...
properties:{
name: {
dataType: "string",
// ...
},
// ...
}
// ...
});

This change propagates to all the rest of the types used internally and in the public API, especially to all the types that had EntitySchema as a generic type argument.

For example EntityValues (representing the data related to an entity) had the signature EntityValues<S extends EntitySchema<Key>, Key extends string> and now it is simply EntityValues<M>. You may use EntityValues or any other type that includes a schema as a type if you have callbacks in place or have implemented custom views.

This affects in an equal way all the types that are exported. In order to migrate to the new version you need to make sure that you don't have any references like EntityCollection<typeof productSchema>, like the ones we had in the previous examples. In that case you can create your Product type if you want better type checking or simply remove it.

Motivation

Let's face it, the type system related to schemas until now was a mess.

It had become overcomplicated and was not providing enough type information in the callbacks. Not it is much straightforward.

Robustness

I have always found it annoying all the Javascript frameworks that use the module.exports system for configuration. I find myself going always back and fort from the IDE to their website to get the information I need, even if I have an idea.

Configuration as code with a strong type system is a whole other level.

The new system is now able to tell you exactly what you are configuring wrong, or suggest the props you are looking for. The following is a configuration error because we are assigning the multiline config, which applies only to strings, to a number property:

// ...
name: {
dataType: "number",
title: "Name",
config: {
multiline: true
},
validation: { required: true }
}
// ...

So it indicates a type error:

Configuration error

Migration examples

For example, if you had a callback including EntityValues, you would know the property keys you had defined, but not the types.

import { buildSchema } from "@camberi/firecms";

type Product = {
name: string;
price: number;
}

export const productSchema = buildSchema<Product>({
name: "Product",
onPreSave: ({
schema,
path,
id,
values,
status
}) => {
// Now values is of type `Product`
console.log(values);
return values;
},

properties: {
name: {
dataType: "string",
title: "Name"
},
price: {
dataType: "number",
title: "Price"
}
}
});

With this update you get a complete type system in all your callbacks, which will help prevent errors.

Use without specifying the type

There is a way to get the same type validation without indicating the type explicitly. You can wrap each property with buildProperty to get the same result

import { buildSchema, buildProperty } from "@camberi/firecms";

export const productSchema = buildSchema({
name: "Product",
onPreSave: ({
schema,
path,
id,
values,
status
}) => {
// Now values is of type `{ name: string; price: number; }`, so
// equivalent to the previous example
console.log(values);
return values;
},

properties: {
name: buildProperty({
dataType: "string",
title: "Name"
}),
price: buildProperty({
dataType: "number",
title: "Price"
})
}
});

This way of building your schemas is not encouraged, but it may be useful for simplifying your migration.

In case you need to retrieve the type of the schema you have created, we now include a utility type called InferSchemaType that could be useful if you had code like buildCollection<typeof productSchema>, which now would simply turn into buildCollection<InferSchemaType<typeof productSchema>>

We know that it can be a bit frustrating to migrate code to a newer version and fix breaking changes, but we are convinced that this is a change for the better, making our life and our users easier 😉

Affected types and methods

All the following types and methods have seen their types changed from <S extends EntitySchema<Key>, Key extends string> to <M>

  • EntityCollection
  • AdditionalColumnDelegate
  • PermissionsBuilder
  • ExtraActionsParams
  • FilterValues
  • EntityCustomView
  • EntityCustomViewParams
  • EntitySaveProps
  • EntityDeleteProps
  • Entity
  • EntityValues
  • FieldProps
  • FormContext
  • CMSFormFieldProps
  • Properties
  • PropertyBuilderProps
  • PropertyBuilder
  • PropertyOrBuilder
  • listenCollection
  • fetchCollection
  • fetchEntity
  • listenEntity
  • listenEntityFromRef
  • createEntityFromSchema
  • saveEntity

And some other components that are only used in advaced use cases.

Hello! Hola!

· 4 min read

Welcome to the FireCMS blog!

We will use this blog to keep you up to date of the latest updates regarding FireCMS, as well as case-studies!

But first, a quick introduction on how we ended up building our own generic headless admin panel/CMS solution based on Firebase!

We started Camberi as an apps and web development agency in 2018. We all were experienced Firebase users, and we found it was a great fit to start new projects, requested by clients.

Motivation

Usually clients would like to develop an app or a webapp, and most times they would need an additional tool for backend administration. We built 3 tools for different projects, that were similar but slightly different. They were all React projects. We soon realized a generic solution would help us a lot, so we thought: There must be a generic headless CMS based on Firebase/Firestore right?

Right! There were some solutions out there, but we found problems with all of them, which stopped us from using them:

  • Either they were generic CMS tools that were not optimised for the Firestore data structure, with its pros and cons (such as React Admin, despite being a great tool).
  • Or they impose a specific Firestore data structure, which means that are not suitable for every project. This is the case for Flamelink, which is a commercial solution based on Firebase, which follows a philosophy more similar to Wordpress.
  • Or they don't provide enough features. The best solution we have found is Firetable, which shares some core concepts of FireCMS, but we find a bit limited in some Firestore specific areas. It is opinionated on a few things, like the way users are stored for example, and we don't like that. They provide a lot of good widgets but not the possibility to use your own easily.

With all the previous factors taken into account, and a pandemic keeping us home, we decided to unify all the tools we had built into a generic one!

Companies put a lot of effort into building their client facing apps but internal admin tools tend to be the ugly ducklings, with huge productivity implications.

Core concepts

Pretty soon we knew what we wanted to build. Firestore is a no-SQL database with a data structure that consists of collections, that contain documents, that can contain subcollections, and so on. We need that our UI reflects that structure, with an arbitrary level of nested collections.

It is also crucial that that beautiful UI is customizable, and we have added multiple customisation points based on both our needs and your input.

Our headless CMS must allow developers to extend it in any way they need, while keeping it extremely simple to kickstart a new project, with the bare minimum configuration. We need sensible defaults that can be overridden or extended.

Features

FireCMS allows setting up a CMS in no time, just by introducing your collections and document schemas as input, and it renders beautiful editable spreadsheet-like tables and forms. It also builds all the navigation and authorization views automatically, so you don't have to. All the common use cases are covered out of the box, including strings, numbers, booleans, arrays, maps, references to other documents, timestamps... We also provide more advanced use cases, like:

  • String enumerations with customization.
  • Handling of files such as images, videos or anything really in Google Cloud Storage.
  • We automatically generate complex fields for references to other collections, just by providing the collection path. Also, we handle correctly arrays of references.
  • Markdown fields, with preview
  • Complex typed array structures: such as an array that contains objects of type text, or images, or products like in our blog example!

Again, besides the basic and advanced use cases that are bundled with the library, the CMS allows the developer to customise and override most aspects of it!

Take a look at the docs if you would like to know all the possible options!

We hope you enjoy using FireCMS as much as we do while developing it, and I would like to take the change to thank all the external contributors with feedback and PRs.

You rock! 🙌

Sign up to our newsletter to get the latest news and updates. No spam!