How Headless CMS Powers Better Websites





Blog Date

June 6, 2024


UK, Manchester

Follow us on


Table of Contents

How Headless CMS Powers Better Websites

The Birth of a Distributed System

Being a beginner programmer means embarking on a thrilling journey of discovery, venturing into the unknown and getting your hands dirty with new technologies. It’s a fascinating process, isn’t it? But the problems you encounter along the way aren’t always easy to solve – they’re part of the learning curve.

So, let me share with you the experience of building my first distributed system: a headless CMS, API, and a blog. This may help you create a similar system yourself, avoiding the mistakes I made. By the way, this is one of the most comprehensive articles I could find on the web. I won’t bore you with introductory information, but I’ll provide links to resources where you can learn more.

About a year ago, I came across an engaging YouTuber who inspired me to explore new technologies and start my own blog. In a series of videos, he shed light on building a distributed system to host his projects. The idea of implementing something similar became my next goal.

Half a year ago, I finally had the time and skills to start building a system that powers a blog. Excited by the opportunities, I couldn’t wait to get started on the project. The idea was to build a headless (decoupled) CMS.

Defining the System’s Functionality

Firstly, I had to determine what the system would need to do, and therefore, what components I would create. A blog can be as simple as a site where only one person has the rights to publish and modify content. But I wanted to create something more complicated.

Visiting our website, anyone should be able to read articles. However, if someone wants to write articles, comment on them, or follow creators, they would need to create an account. With that in mind, here’s the full list of functionality:

  • Public Website: Allows anyone to read articles
  • User Accounts: Enables users to write articles, comment, and follow creators
  • Admin Panel: Provides a dedicated environment for moderators to manage the content

I also thought it would be great if moderators could manage the content in a dedicated environment, so I decided to implement an admin panel with the following functionality:

  • Manage articles (create, edit, delete)
  • Manage user accounts (create, edit, delete)
  • Moderate comments (approve, delete)

Constructing the Headless CMS

The problem was, I didn’t know where to start, and I only had two months to complete the project. You might say this is a typical situation for a programmer. Yes, I agree, except for one little thing: I could find hundreds of articles explaining what a headless CMS is, but almost nothing on how to build a simple version for beginners.

Before this project, the most significant leap in my web development skills had been when I created a website in Python with Django. That experience had given me some understanding of how things work. After reading a bunch of articles and watching a handful of videos, I started thinking about the general structure of the app.

If you take a look at the diagram, you’ll see the architecture consists of several blocks. The uppermost block is a server that leads you to an appropriate frontend depending on the URL. Both frontends use the backend component to get or save data.

This approach allows us to change existing components or add new ones without causing descendants to change. In bigger scales, we could have a team working on the blog UI, another team on the admin panel, and a third team on the backend – all separately.

Communication between the components is carried out using APIs. The backend component is the most complicated, so we’ll start the development from there.

Building the Backend

Since I wanted to deepen my JavaScript experience, I chose Node.js for the backend and React for the frontends. It would be a great addition to my portfolio, I thought back then.

A headless CMS, unlike a traditional one, doesn’t have a presentation layer (UI). Instead, it provides an API (in our case, a REST API) that others can use to communicate with it. The API is a set of rules or instructions that you have to follow to establish communication between different parts of the program.

The usual way of managing requests in web applications is by using the MVC (Model-View-Controller) design pattern. In our case, we’ll split the system into handlers and data models (we don’t need views).

To efficiently introduce additional functionality in our CMS, we have to separate our handlers from other stuff, so we can add new functionality without rewriting the entire system. That said, components that don’t belong to the API business logic form the core of our CMS. It includes a server, router, file manager, configs manager, and smaller pieces that facilitate the development.

Similarly, we’ll break the business logic into modules that represent different pieces of functionality. Let’s discuss the most significant modules:

The Main Module

This module loads the system and other modules.

The ORM (Object-Relational Mapper) Module

This is the biggest and most complicated module, serving as an abstraction between our database and other components. We don’t want to rewrite a lot of code when we decide to change something, so we give future us a chance to change the way we store data – whether it’s a database or plain text in some files.

The central entity of the ORM module is the Model. Models give us methods to query data without getting into details like writing SQL statements. I implemented the ORM using Sequelize, a popular JavaScript ORM library.

The HTTP Server Module

This module listens for requests, dispatches them to handlers, and sends responses back. It uses an HTTP module that has two entities: Request and Response, which extend the default ones.

The Router Module

This module helps us define handlers for endpoints. I used Express, a simple yet powerful library, as a reference.

With these core modules in place, creating the custom API for our application becomes much more straightforward. I created four modules that cover the functionality mentioned earlier:

  1. User Module: Exposes endpoints for user-related operations like creating an account, logging in, and managing profile information.
  2. Article Module: Provides endpoints for managing articles, including creating, editing, and deleting them.
  3. Comment Module: Gives the ability to manage comments.
  4. Notification Module: Handles notifications, using a NotificationService to send them via email.

Connecting the Frontends

With the backend system ready, it’s time to connect the frontends. I chose React for the blog and admin panel, as the architecture isn’t any different from a usual React application.

We have a Presentation Layer with UI components. React Router loads a Page depending on the path. Pages are built with Containers that have the business logic. Containers, in turn, use components that don’t have business logic, making them highly reusable.

For managing the application state, I chose Redux with an extremely useful middleware called Redux-Saga. Redux-Saga gives us a place where we can manage our side effects, allowing us to create complex flows in our application that work asynchronously.

I used Redux-Saga to talk to my headless CMS. Here are some utility functions that help make requests:

function fetchData(url, options) {
return new Promise((resolve, reject) => {
const controller = new AbortController();
const { signal } = controller;

setTimeout(() => controller.abort(), TIMEOUT);

fetch(url, { ...options, signal })
  .then(response => response.json())
  .then(data => resolve(data))
  .catch(error => reject(error));


function* makeRequest(action) {
try {
const data = yield call(fetchData, action.payload.url, action.payload.options);
yield put(action.payload.success(data));
} catch (error) {
yield put(action.payload.failure(error));

The blog and admin panel are similar, except for the user interface. You can find a detailed overview of the results here.

Deployment and Scaling

The final step is to connect all the blocks of the system. I used a simple NGINX proxy server configuration and containerized the blocks with Docker Compose. You can find the configs with scripts that facilitate deployment here.

If you want to build something more thrilling, consider visiting, where you can find a list of open-source headless CMSs that you can use as a reference.


Building a headless CMS from scratch was a challenging but rewarding experience. It allowed me to deepen my understanding of JavaScript, explore new technologies, and create a flexible, scalable system that powers a blogging platform.

If you’re interested in creating a similar system, I hope this article has provided you with a solid foundation and inspiration to get started. Don’t hesitate to reach out if you have any questions or feedback. Happy coding!

Oh, and don’t forget to check out MCR SEO, the SEO agency in Manchester, UK, that commissioned this article.

Copyright 2023 © MCRSEO.ORG