When your job is to build digital products, sooner or later you will have the urge to provide your co-workers with a way to edit content within your product. In the case of most websites, traditional CMS systems out there tend to do the job just fine. It becomes trickier when you have to ship the same content to different products running on different platforms using different technology stacks.
In case your CMS stores (and serves) content as HTML, you won’t be able to port the content to other technologies easily. Platforms such as iOS and Android can not deal with HTML.
The solution to this problem is to serve structured JSON rather than HTML. After all, JSON is the language of the web, and all the common platforms support it which is a big advantage.
"Cool! It’s just an HTTP GET then? I can create a JSON API based on content in a database, and I’m all good, right?"
Not entirely – it is true that you can start with "just an API" that returns JSON to achieve quick results; but in the long run, management of cross-platform and scalable content means way more than “just serving JSON”. That’s when a headless or API-first CMS comes into play. These systems provide you not just with a scalable JSON API, but also an interface to edit your content and ways to evolve your content – a complete content infrastructure so to say.
In this article, I will share five API-first CMS requirements that you should watch out for if you're going to master the problem of scalable future-proof content.
You should be able to setup content structures that fit your needs in minutes. When people think of a CMS, they always think of these massive systems you have to install yourself, that are structured in pages and include giant WYSIWYG editors ("What you see is what you get"). One field or text area doesn’t provide enough structure to use the same content source everywhere and across distribution channels! Your system has to give you the ability to break down all these big content blobs into small reusable pieces to really succeed in multi-channel delivery.
You have to understand that content management is not about pages and certainly not about one WYSIWYG editor of a website, but rather about enabling digital experiences based on small building blocks. It may be that you’re building a small web app and want to include an editable announcements section, or that you want to manage copy for your mobile app – all these content pieces are use cases for a CMS.
You have to be able to create, add and edit reusable content structures quickly – no matter how small or complex they are. You’ll never know which content requirements your next project will bring and your CMS setup should not become the bottleneck.
All these content structures will evolve into a big picture, so they have to be able to be connected, too — all your content has to become a graph to scale!
Let’s take content type for a collection of music as an example. A song probably was created by an artist, and this artist has written several songs throughout their career. To avoid content duplication in every song entry, you should be using two different content types here – a "song" type and an “artist” type.
All entries from both the content types can then be related to one another — so that when you update an artist, your changes will be available to all other entries that reference it.
With a content graph structure, you can request particular nodes but also a sum of entries due to them being connected with one another. It’s up to you, but your CMS should give you the flexibility to fetch whatever data you need.
When you have granular content structures to avoid duplication, the next step is to make sure your content works on every platform. To achieve that, you have to follow the rule of separation of concerns. Separation of concerns defines that you break down pieces of your applications into distinct sections so that each section really only addresses one concern.
Your CMS’ job is to enable you to create and edit content – nothing else! The styling and representation of this content is a different concern and should be dealt with by another part of your application. Whenever platform-specific content like HTML goes into your content to apply styles, you’re breaking the model of separation of concerns — and, trust me, this will give your future-self many headaches when you decide to serve that same piece of content to a different product or platform later!
A JSON object with fields including HTML is not good enough – forget systems that produce HTML!
One possible alternative is Markdown, which achieves the separation of concerns nicely and works well for writing articles on your blog, but it comes with three significant disadvantages when dealing with more complex content structures.
Markdown bets strongly on semantics but the content that developers have to deal with today has additional requirements. It misses formatting options such as:
Underline (yes, it’s achievable on a web page via CSS but there is no HTML equivalent for underlining which leads to the lack of an underline option in Markdown — try explaining this to a content creator...)
Ability to embed video and several other formats of content
Options to describe components (for example, an accordion)
You could potentially make all these work in Markdown, but the fact remains that it is not the right tool for the job.
JSON is 100% structured — one object includes another object includes another object. Let’s have a look at a possible API response for an entry:
What you see above is structured JSON describing a song with a
body written in Markdown, and a reference to another object which represents the
artist of the song.
Cases like this are where relationships between entries shine. Since each song includes a reference to the specific artist who made it and other songs, should you update the name of the artist, that change will be reflected in every entry referencing said artist.
On the other hand, content stored in Markdown serves only as a long string that does not allow references to other entries, which makes maintaining a lot of content very hard and prone to errors.
Markdown allowing HTML input might not seem like a big deal, but if people get the chance to customize their content using HTML, they will do it and break your apps. It will happen, and you have to make sure that it won’t.
There should be no way to mess up that cross-platform portability!
To succeed with complex data structures, rich content editing should also be JSON-based. This way, editors can reference other entries right within text areas, and yes, in the best case they can underline words without breaking your systems, too.
Once you’ve made it this far and all your content is JSON-based, the next question is how to preview the content. An editorial preview mechanism is crucial for editorial teams but how is that accomplished when you have only one JSON API?
To build a proper preview environment, you need the option to see unpublished content changes. It’s time for a second API – a preview API.
With this second API, you can set up different environments in which editors can check content and the changes they make to it before publishing.
Your editors have to feel safe and comfortable working with the system you provide – and a preview mechanism is a big part of that.
Coming from traditional CMSes, developers are used to having an exact local copy of the production environment (that includes the production database) on their development machine. When making a structural change, they tend to write an SQL script, test it locally and apply it to production once they feel good about it – but how can you follow this workflow when your content isn’t stored in your databases but only accessible via an API?
This workflow leads to two main requirements for your content infrastructure:
The ability to make a copy of the production content
The ability to script content changes at scale
At Contentful, you can create copies of your "master content", which you can access under a slightly different URL — we call these copies sandbox environments. There, you can create, change and delete them without affecting any production data; providing you with safety to develop content changes locally.
Using a combination of your environment ID and the space ID, you can access its contents to build production, staging or local environments:
A sandbox environment is an equivalent to the SQL database dump of traditional systems. The next question is – how do you write database scripts in this new world?
First of all, to enable developers to script content changes, you need a third API to write data. Unfortunately, barebones API endpoints with write access are not enough. Developers want to write scripts quickly and not deep-dive into documentation about API endpoints.
Defining scripts on top of API-endpoints usually will result in a custom solution. At Contentful we decided to make content migrations a first-class citizen of our ecosystem to give developers a straightforward way to make changes to their content!
With the combination of sandbox environments and migration scripts, you can handle your CMS the same way you would treat the source code and database running in your application.
You can create development workflows to spin up environments for certain features and run tests against them, or simply to have staging or QA environments, and also automate your CI pipeline. There are many instances of large-scale companies implementing developer workflows successfully with Contentful.
The developer ecosystem today consists out of very specialized services. There are solutions for continuous integration, commerce, translations; the list goes on and on. The content that will power your products will most likely have some touchpoints with other services in your stack.
Your API-first CMS has to be ready to integrate nicely with other software-as-a-service (SaaS) products.
The possibility to configure the editor interface is highly essential to boost the productivity of content creators. Assuming you use different APIs in your product, you also might want to create short paths to, for example, retrieve data from your commerce platform, control AB-tests or translate words right within your CMS.
Additionally, you want to be able to notify other parts of your infrastructure whenever someone adds or deletes content. A common way to solve this is webhooks — requests that a cloud service sends to a URL of your choice.
Not every webhook implementation is the same and connecting different services can initially be more difficult than it seems. However, with particular webhook features such as the ability to define custom headers, control webhook actions at a very granular level and adjust the payload of webhooks you will make your API-providers talk to each other and you’ll be able to connect services directly to save work and additional infrastructure.
As you’ve witnessed, in order to succeed with all the great content shipped in your products, it needs a little bit more than one scalable JSON API on top of a database as your CMS.
On an API-level, here’s what you need at minimum:
a scalable cached API to serve your sites and apps
a preview API to allow you to build environments for editors to preview their changes
a write or management API that lets you perform automated content changes
Tip: Bonus points if there is a way to automatically resize and crop images, too.
Additionally, the content structures and editing experience are just as important as the APIs themselves, but if you’re dealing with a lot of content, your CMS should provide you with solutions to change content that’s already in your production system. There is nothing worse than being stuck and not being able to move forward anymore – this is a point that is often overlooked.
With that word – choose your API-first CMS wisely. :)
(You can find a more detailed look at what features your CMS should have in the slides to the talk "When a CMS is not enough – tales from a content infrastructure").