Skip to main content

· 12 min read


If you are working on any kind of public-facing digital project —no matter if it's a website, a web app, a mobile app or desktop app — you will likely need a Content Management System. There are a lot of options to chose from, and different solutions are better suited for some needs than others. We can distinguish some categories straight away:

  • General purpose or web oriented
  • Headless or traditional
  • By access to data APIs (GraphQL, REST, SDKs)
  • Cloud based or self-hosted

We are building this guide to help you pick the right CMS for your project. We will be updating it regularly, so make sure to check back often.

One of the motivations for this guide is to help users understand the differences between CMSs. Despite creating FireCMS, we are not trying to promote it as the best solution for everyone. We are just trying to help people understand the trade-offs of different solutions. This is the same thing we say to our users when they ask us for advice on what solution to use.

General purpose or web oriented

The first thing to consider is whether you need a general purpose CMS or a web-oriented one. A general purpose CMS is a tool that can be used to manage content for any kind of project (apps, desktop, web), while a web-oriented CMS is a tool that is designed to manage content for websites.

Web oriented CMSs are built with the assumption that the content will be displayed on a website, and they usually provide a web editor to edit the content. This is not the case for general purpose CMSs, which can be used to manage content for any kind of project, including mobile apps, desktop apps, etc.

Web oriented CMSs are usually simpler to use, but they are also more limited in terms of features and integrations. They provide built-in support for pages, headers, footers, navigation menus, and other common website features, but they are not as flexible as general purpose CMSs. Also, they will typically have a published flag (or equivalent) for each entity. Of course, nothing stops you from using a general purpose CMS to manage content for a website.

Do you need a blog? A web-oriented CMS will likely have a built-in blog solution, while a general purpose CMS will not.

Examples of web-oriented CMSs are Wordpress, Prismic or Storyblok. Those are the way to go if your main goal is to build a website and a web editor is useful to you.

General purpose CMSs can be used to manage any type of content. Think of things like the menu of a restaurant or a delivery app. Or the exercises and videos of a fitness app. Or the podcasts in a podcast app. If you are working on a mobile app or a web app where you need to manage any content related to your business, FireCMS is a great option. It has all the advantages of other general purpose CMSs, but it uses Firebase as a backend, so you have access to all the robustness, extensibility and features of Google Cloud.

Headless or traditional

Traditional CMSs are the ones that provide a web editor to edit the content, and they will be responsible for rendering it on the website. So the admin interface and the website are tightly coupled.

Headless CMSs are the opposite: they are not coupled to the rendering of the website and are in charge of managing the content exclusively. CMS and website are different software components in this case. They provide an API to access the content. The website is responsible for rendering the content, and it can be built with any technology.

Headless CMSs are more flexible than traditional CMSs, but they require more work to build the website. The benefit is that you can build it with any technology you want.

Note that a CMS can be web-oriented and headless at the same time. In this case, the CMS will provide a web editor to edit the content, but it will not be responsible for rendering it on the website. Examples of this are Prismic, Contentful or Agility CMS.

Examples of headless and general purpose CMSs are Strapi, GraphCMS or Sanity

FireCMS is a headless and general purpose CMS. It is a general purpose CMS that can be used to manage content for any kind of project, including websites, web apps, mobile apps, desktop apps, etc.

Access to data APIs

The next thing to consider is the APIs provided by the CMS. The most common APIs are REST and GraphQL. REST APIs are the most common, but they are not as flexible as GraphQL APIs. GraphQL APIs are more flexible, but they are a bit harder to use.

Some CMSs provide SDKs to make it easier to use their APIs. SDKs are usually available for the most common languages, like JavaScript, Java, Python, PHP, etc.

FireCMS uses Firestore as a backend, so it benefits from all the native SDKs provided by Google. This is a big advantage, because it means that you can use the same SDKs to access the CMS and to access the Firestore database. At the same time, having Firebase as a backend means that you can use all the Firebase features, like authentication, hosting, functions, etc. No other CMS can offer this.

Cloud based or self-hosted

The last thing to consider is whether you want a cloud based CMS or a self-hosted one. Cloud based CMSs are hosted by the CMS provider, and you don't need to worry about hosting and maintenance. Self-hosted CMSs are installed on your own servers, and have a little more overhead, but also better flexibility.

Other considerations

Main user type

If your main user type is a content editor, you should consider a CMS that allows them to edit the content without having to write code. Also, you want to make sure that the CMS is easy to use, and that it provides a good user experience, as well as preventing users from making mistakes, that could potentially break the apps linked to the underlying database.

Data portability

If you are planning to use a CMS for a long time, you should consider the data portability. You want to make sure that you can easily export the data from the CMS, and that you can easily import it in another CMS.

Also, you want to check the license of the CMS. Some CMSs are open source, while others are proprietary.

CMSs comparison

Check the comparison table below to see which APIs are provided by each CMS.

NAMEFireCMSAgility CMSButterCMSContentfulGhostGraphCMSKeystone JSPrismicSanityStoryblokStrapiWordpress - unite cms
Open Source
Cloud ServiceWIP
On Premises Installation
Cloud Service Hosted in Europe~~~~
Commercial Support Available?
User Management
Role Based Permissions
Document Level Permissions
Web builder
Real time support
Search: Full Text Search~~
Client Side Forms~
Plugin System
Customizable UI~
Content Trees~~
Nesting fields/elements~
Image: Manipulation~~
OAuth 2.0 Support~~
CDN Support~
Backup Feature~~
Web Hooks
GraphQL: API
SDK: Java~
SDK: C#~
SDK: JavaScript
SDK: React~
SDK: AngularJS~
SDK: TypeScript~

Picking a CMS is a very personal decision, and there is no one-size-fits-all solution. You should consider your team's experience, the project's requirements and your budget.

· 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

· 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 Camberi 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 or directly at 😊

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!

· 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;

const productSchema = buildSchema<Product>({
// ...
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.


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.


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: ({
}) => {
// Now values is of type `Product`
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: ({
}) => {
// Now values is of type `{ name: string; price: number; }`, so
// equivalent to the previous example
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.

· 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.


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.


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! 🙌


Learn how to get the most out of your project with the help of our consulting team.
Get in touch
Sign up to our newsletter to get the latest news and updates. No spam!