Back to blog

Building APIs FAST with Strapi, an overview

Posted

I've been using Strapi for a few months in different scenarios, from quick prototypes and small test to more serious projects like the web application I'm working on (theLifeBoard.app). Although I've been using it for months, I haven't written an article about it yet and since a few days ago, the Strapi team announced the release of the v3 stable version, what a better time to write one (or maybe more) than now?

So what is Strapi? If you're not familiar with it, this is how they define it in their FAQ

Strapi is an open-source, Node.js based, headless CMS to manage content and make it available through a fully customizable API. It is designed to build practical, production-ready Node.js APIs in hours instead of weeks.

A Content Management System that provides an API in hours. Sounds good, doesn't it? Let's create a simple project to get a taste of it.

A quick example

Let's say we want to build an API to manage books. Only authenticated users can create, edit or delete them but anyone can query them. Our endpoints would be:

Database setup

The first thing we need is a database to store our data. Strapi supports SQLite, MySQL, PostgreSQL and MongoDB so you can use any of them. For this example, I'm going to use MongoDB running on Docker, which, for me, it's the easiest way to manage database services in a local development environment. You can check this article in which I explain how to install Docker among other things.

Once you have Docker running, follow these steps:

Scaffold the Strapi project

To initialize and generate the project we need to run npx create-strapi-app your_project_name. For example npx create-strapi-app demo-strapi. This will start a guided installation. Choose Custom type and select the options as detailed below:

The installation will take a few minutes. Once finished you can start your app running npm run develop from the project folder and the application will start in port 1337 by default.

Strapi first run

The first time we start a Strapi application, it will ask you to create an administrator user. This will be the user we'll use to create content types, manage permissions, install plugins etc.

Once the user is created, we'll be in the administration UI and we can start creating our Book model in the Content-Types Builder section. Select Create new collection type and enter the name of the model, in singular. In our case, it would be Book.

Next you'll have to select the different attributes and types for our Book model. I selected the following ones:

  1. title
  1. pages
  1. publishDate
  1. summary:

As you can see, in the advanced settings we're adding some validations for required and unique fields. We can event include more detailed validations by using a RegExp pattern if we want.

Once our model is defined, click save and the application will restart.

Managing Content within the UI

Now that we have created our Book Content Type we can start adding books directly from the administration UI. Go to the Book Collection Type and you'll see an "Add New Book" button, which will show a form like the one below:

Strapi Content Management

As you can see, the input fields match with the data types of the attributes we selected while creating the content type. From this section of the UI you'll be able to create, edit or delete items for all the content types, which is great but the best part is that Strapi has also generated a REST API we can use to interact with the content types. Let's review how it looks like.

Strapi project structure

Once you've created the first model, if you open the project folder, you'll see that it has generated two folders: config and an api.

Inside the config folder you'll find the application server specific configuration, like the database details (the ones you entered during the installation wizard), the host, port and even a cron.js file in which you can specify scheduled functions to run.

Inside the api folder you'll see one folder for each content type created, in this case one named book. Each one will have the following folders inside: config, controllers, models and services. Inside these folders we have the files we can modify to extend and customize our API:

By default, the generated REST API will manage basic CRUD operations (Create, Read, Update and Delete) so if this is all you need, you're ready to go 😉.

Setting up the permissions

Permission management is Strapi is a pretty straight forward in the Roles & Permissions section of the UI. We have two different roles available by default: Authenticated and Public, although we can create as many roles as we want. To allow actions in each role, select the role and in the Permissions section, you'll see all the Content Types available and all its available routes. You'll just need to select the permitted routes for each role and click save. In my example, I'm allowing all actions for the Authenticated role:

Strapi permission management

And just the count, find and find one actions for the Public role:

Strapi permission management

Once permissions are configured, our API is ready to test. But how do we create the users for the Authenticated role? Let's see check that out.

Registering and login users

Strapi provides default endpoints to manage API users. These are:

Register:

{	
	"username": "",
	"email": "",
	"password": ""
}

Login:

{	
	"identifier": "",
	"password": ""
}

Note: the identifier could be the username or the email.

Both return a similar response, including the user details, role and a JWT:

{
    "jwt": "eyJhbGciOiJIUzI1NiIsCI6IkpXVCJ9.....",
    "user": {
        "confirmed": true,
        "blocked": false,
        "username": "user_one",
        "email": "[email protected]",
        "provider": "local",
        "id": "5ee0cafb6ec1410fda381181",
        "role": {
            "name": "Authenticated",
            "description": "Default role given to authenticated user.",
            "type": "authenticated",       
            "id": "5ee0c6f136637b0e7426a2a5"
        },
    }
}

Note: Strapi also provides endpoints to for the forget and reset password functionalities. You can find more info here.

We'd need to send the JWT in the Authorization header in order to access the authenticated protected routes. If we send a request with no JWT (or with an invalid one) to a route only allowed to the authorized role, we'll receive a 403 Forbidden error.

Now we should be able to register a new user, login and with the JWT recived, send a POST request to create a Book.

Strapi Postman API request

To query the API we just need to send a GET request to /books, no Authentication required.

Conclusion

This was just a quick overview of what Strapi offers. A quick summary would be that Strapi allows you to generate a Node.js REST API with authentication in a matter of minutes. That's the main sell point for me but it offers a lot more. The administration UI allows you to manage the content without the need to create a front end yourself. It has model relationships out of the box, plugins to manage permissions, send emails, manage media files, use OAuth authentication from different providers, GraphQL, Cron jobs and more. These means that you can basically build and entire back-end for your service or application with Strapi.

Other Pros

The not-so-good

Strapi is great, but it's not perfect. Here are a few of the downsides I've faced while using it:

I hope this article helps you decide if Strapi is a good choice for your next project. I really recommend it as it could help you save time developing APIs (I can't remember how many times I've scaffolded an Express app...). However if you're new to back-end development, you might get lost if you try to add custom functionalities so make sure you get familiar with concepts like routing, controllers, services etc by reading the docs first. And if you have any questions, you can ping me on Twitter or ask the community in the Slack help channel.

Happy coding!

Included in categories

coding API Node.js

Did you enjoy this article? Consider sharing it on social media and following me on Twitter 🤙