5 Things I love about Strapi, a Node.js headless CMS

Published on 25 Nov, 2019 · 8 minutes read

Michele Riva
Founder @Hackdoor.io

One year ago I started sto develop the backend for the website you’re currently browsing on.
I’ve tried different approaches, different technologies and even different programming languages.
Then I started to look for a CMS that could help me to integrate a number of feature with ease… but I couldn’t find a CMS that satisfied me at all.
Then I discovered Strapi, an amazing open source headless CMS that had everything I was looking for.
I’m not going to review it in depths, I just want to focus on the five things I love about that awesome CMS:

1) Getting started in less than 2 minutes

When I started to build websites with a CMS, I started with WordPress. I’ve always thought “there’s no easier way for getting started with a CMS!”
Well… I was completely wrong! With Strapi you can get started in one minute and an half!

Now you may be wondering: “ok great, but how do I setup my database connections?”.
Amazing question!
In Strapi you have three different environments: development, staging and production.
By default (in the development environment) Strapi will setup a SQLite connection, so you don’t need to boot up a MongoDB/Postgres/MySQL instance just for the development process!
Why did i mention these three databases? Because Strapi is database-agnostic. You can switch from one db to another with ease (and we actually did it on this website migrating from Postgres to MySQL in literally 15 minutes!).

You don’t like the default database connection? That’s ok, you can bootstrap your new Strapi instance as follows:

npx create-strapi-app <appName>

And a prompt will ask you all the informations needed to establish a database connection.
When you’re ready to test your Strapi instance in staging, you can specify a database connection just for that particular environment (and same for production)!
Pretty awesome, isn’t it?

2) GraphQL out of the box

GraphQL is an amazing technology. I’ve already written about it in the “Writing a GraphQL server” article some time ago.
There are a lot of CMS that exposes GraphQL APIs, but just a few of them are completely free and open source.
At the beginning, I just wanted to test Strapi’s functionalities, and the GraphQL plugin left me amazed! You can install it from the backoffice and you’ll be ready to run your queries in literally 30 seconds!

The quality of these GraphQL queries will leave you amazed, I promise! Absolutely the easiest and higher quality GraphQL interface I’ve ever met into a headless CMS.

3) Permissions

When you’re building your APIs, you may need to restrict their access to a specific group of users.
For instance, you may have some sensitive data that must be protected and cannot be shared publicly.
Strapi makes it extremely easy to manage that kind of situations using its amazing dashboard:

In just few seconds you’re able to setup an incredible amount of permission rules to secure your REST/GraphQL APIs!
But how do you authenticate in order to gain access to these routes?
Well, Strapi releases a JWT token that you can use inside an authorization header for your HTTP requests. Pretty amazing!

4) Relations

Handling relations between data inside your Strapi instance is incredibly easy.
Let’s say that you’re building your blog and you have multiple authors: inside your database you may have both “Users” and “Articles” tables right? How would you handle the relation between an article and its author (which is an “user”)?

Is it really that easy? Yes, it is! You can handle an incredible amount of relations inside your Strapi instance using just its backoffice, which always leave me speechless.

5) Programmatic

Most of the time, when you’re using a CMS you need to make some customizations in order to adapt its behavior to your business’ needs.
Well, Strapi (once again) has an amazing solution for customizing its behavior following your requirements.
One thing I didn’t mention yet, is that most of the settings that you’re customizing using the Strapi backoffice are saved inside some configurations files on your filesystem.
For instance, we’ve previously seen that we’ve created an “Articles” table inside our database, right?
If you’re browsing to /api/articles inside your Strapi folder, you will find the followind directories:

  • config
  • controllers
  • models
  • services

that may remind you of a MVC framework… probably because Strapi behaves as an MVC framework!
In fact, you can do the exact same backoffice tasks via API or editing the files inside the above directories.
For instance, do you want to edit your API routes, you can just customize the /api/articles/config/routes.json file:

  "routes": [
      "method": "GET",
      "path": "/articles",
      "handler": "Articles.find",
      "config": {
        "policies": []
      "method": "GET",
      "path": "/articles/count",
      "handler": "Articles.count",
      "config": {
        "policies": []
      "method": "GET",
      "path": "/articles/:id",
      "handler": "Articles.findOne",
      "config": {
        "policies": []
      "method": "POST",
      "path": "/articles",
      "handler": "Articles.create",
      "config": {
        "policies": []
      "method": "PUT",
      "path": "/articles/:id",
      "handler": "Articles.update",
      "config": {
        "policies": []
      "method": "DELETE",
      "path": "/articles/:id",
      "handler": "Articles.delete",
      "config": {
        "policies": []

Inside the config.policies property, you can define the permission rules that allows that specific route to be called via under authentication.
You can also add and customize the controller triggered by a specific rute editing the handler property.
But where do you write the Node.js code for the controllers? Inside the /api/articles/controllers/Articles.js file!

'use strict';
 * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers)
 * to customize this controller
module.exports = {
  myNewController: async (ctx) => {
    ctx.body = {
      jsonResponse: true

Strapi is built on top of Koa, which is a popular and powerful Node.js web framework, so you may already be familiar with its functioning!
The last thing that I want to mention about Strapi is its amazing callback system. Opening the /api/articles/models/Articles.js file, you’ll gain access to an advanced callback system that will help you a lot improving the CMS behavior:

"use strict";
 * Lifecycle callbacks for the `Articles` model.
module.exports = {
  // Before saving a value.
  // Fired before an `insert` or `update` query.
  beforeSave: async (model, attrs, options) => {},
  // After saving a value.
  // Fired after an `insert` or `update` query.
  afterSave: async (model, response, options) => {},
  // Before fetching a value.
  // Fired before a `fetch` operation.
  beforeFetch: async (model, columns, options) => {},
  // After fetching a value.
  // Fired after a `fetch` operation.
  afterFetch: async (model, response, options) => {},

  // Before fetching all values.
  // Fired before a `fetchAll` operation.
  beforeFetchAll: async (model, columns, options) => {},
  // After fetching all values.
  // Fired after a `fetchAll` operation.
  afterFetchAll: async (model, response, options) => {},
  // Before creating a value.
  // Fired before an `insert` query.
  beforeCreate: async (model, attrs, options) => {},
  // After creating a value.
  // Fired after an `insert` query.
  afterCreate: async (model, attrs, options) => {},
  // Before updating a value.
  // Fired before an `update` query.
  beforeUpdate: async (model, attrs, options) => {},
  // After updating a value.
  // Fired after an `update` query.
  afterUpdate: async (model, attrs, options) => {},
  // Before destroying a value.
  // Fired before a `delete` query.
  beforeDestroy: async (model, attrs, options) => {},
  // After destroying a value.
  // Fired after a `delete` query.
  afterDestroy: async (model, attrs, options) => {}

As you can see, you’re able to customize every CRUD behavior of your APIs. This is probably my favorite Strapi feature, ‘cause it helped me to achieve every JSMonday goal in just a few lines of code and an incredibly small amount of time.

Is that all?

Of course no! Strapi is an incredible piece of engineering that allows you to build high quality REST/GraphQL APIs really quickly.
I just wanted to select my five favorite features out of an high number of functionalities that makes Strapi a complete and production ready CMS.
If you want to learn more about Strapi, you can read its documentation here: https://strapi.io/documentation.