Strapi 5: A Self-Hosted Headless CMS That Generates Its Own API
Self-hosted headless CMS in JavaScript and TypeScript that turns visually defined content models into REST and GraphQL APIs, with roles, media library, and i18n built in.
At a glance
- What is it?
- Strapi is an open-source, TypeScript-based headless CMS that builds a REST and GraphQL API from your content models. This review covers its architecture, setup, limits, and who should host it.
- Who is it for?
- Adopt Strapi if you want a self-hosted CMS where developers define content types visually and get a REST and GraphQL API without writing controllers. Skip it if you need a fully serverless CMS, a headless backend with a tiny memory footprint, or a system that ships official Docker images.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem Strapi Solves
Strapi targets teams that want a content management interface for editors but also want to deliver content through an API to a custom frontend, mobile app, or IoT device. Instead of building a custom admin panel and then hand-writing endpoints for each content type, Strapi lets you define the content model once. The system then generates a full API from that model. The intended user is a developer who wants to move fast on the API side while giving non-technical staff a friendly editing screen. The README says it is for building content APIs fast. That is the core promise: no separate backend service to write for basic CRUD operations.
How Strapi Turns Models into Endpoints
The mechanism is a layered backend architecture. The README describes the request flow as Routes, then Middlewares, then Controllers, then Services. When you create a content type with the Content-Type Builder, Strapi registers matching routes. An incoming HTTP request hits the route, passes through any middleware you have configured, reaches a controller that handles the business logic, and finally calls a service for data access. The result is that both REST and GraphQL APIs are auto-generated for every content type. You can customize any layer, but you do not have to. This is a different approach from a framework like Express, where you would define every endpoint manually. Strapi gives you the default CRUD paths and lets you override them when the default is not enough.
Getting Strapi Running: Commands and Config
Installation is a single command: npx create-strapi@latest my-project. That command creates a new project with authentication, permissions, content management, the Content-Type Builder, and file upload enabled by default. The README points to the CLI installation docs for options like TypeScript and --quickstart. For Docker, Strapi does not provide official images. You build your own from your project. The community tool npx @strapi-community/dockerize@latest generates a Dockerfile and docker-compose.yml tailored to your project. That is a real difference from many CMS projects that ship a container image. You are responsible for the Dockerfile, either by using the community tool or writing it yourself.
Built-in Features: Permissions, i18n, and Drafts
Out of the box, Strapi includes a Roles & Permissions system, a Media Library, Internationalization, and Draft & Publish. These are not plugins you need to find; they are part of the default install. The Roles & Permissions system lets you control who can read or write which content types. The i18n feature allows content in multiple languages. Draft & Publish gives editors a workflow where content can be saved without being live. For a headless CMS, these features are the baseline that many teams expect. Strapi bundles them, which saves integration time. The README also mentions Strapi AI, which can automate content modeling, media alt text, and translations. That is a newer addition and the README does not say whether it is free or how it is configured.
Database and TypeScript Support
Strapi supports SQLite, PostgreSQL, MySQL, and MariaDB. That covers the common self-hosted database options. SQLite is useful for local development and small projects, while PostgreSQL is the typical production choice. The project is written in TypeScript and offers first-class TypeScript support. That means you can write your custom controllers and services with type checking. However, the README does not specify which Node.js versions are supported. The requirements are linked, not listed. That is a gap for planning. You have to check the deployment docs before you commit to a runtime. The database choice also affects how you run migrations, and Strapi has migration guides, but the README does not describe the migration process in detail.
Where Strapi Is the Wrong Tool
Strapi is a Node.js application that you host. That means you need a server, a database, and ongoing maintenance. If your team has no interest in operating a backend, Strapi is not the right choice. The README points to Strapi Cloud as the managed alternative, but that is a paid service, not part of the open-source project. Also, Strapi does not ship official Docker images. You must build your own. That adds friction in a containerized environment. Another limitation is that the auto-generated API is generic. If you need highly customized endpoints with complex business logic, you will spend time overriding the default controllers and services. The README does not claim to handle every scenario. It is a starting point, not a finished application server.
Alternatives: Directus and Payload
A direct alternative is Directus, another open-source headless CMS that also runs on Node.js and supports SQL databases. The difference is that Directus works on top of an existing database schema, while Strapi creates the schema from your content types. With Directus, you design your database tables first, and Directus reflects them into an API. With Strapi, you use the Content-Type Builder to define the model, and Strapi manages the database schema. That is a fundamental difference in workflow. Another alternative is Payload, which is also TypeScript-based and integrates tightly with Next.js. Payload is more code-first, where you define your content models in TypeScript code, not through a visual builder. Strapi's visual builder is its main differentiator. If you prefer schema-first database design, Directus fits better. If you want a code-first CMS embedded in a Next.js app, Payload is a candidate.
Maintenance, Upgrade Cost, and License
The repository shows an active release cadence: v5.52.2 was pushed on 2026-08-26, with v5.52.1 and v5.52.0 in the weeks before. That means regular updates, which is good for security but also means you must keep up with upgrades. The README links to migration guides for keeping projects up-to-date. That implies that upgrades are not always trivial. The license field in the repository metadata is listed as unknown, but Strapi is described as open-source. The README does not state a specific license identifier. You should check the actual LICENSE file in the repository before adopting it for a commercial project. The upgrade cost is real: each major version may require changes to your custom code, and the migration guides exist for a reason.
Editorial conclusion
Adopt Strapi if you want a self-hosted CMS where developers define content types visually and get a REST and GraphQL API without writing controllers. Skip it if you need a fully serverless CMS, a headless backend with a tiny memory footprint, or a system that ships official Docker images. Before choosing, verify the Node.js and database requirements for your target environment, test the migration guides for any existing Strapi 4 projects, and confirm that the plugin you need is maintained for v5. Strapi gives you control at the cost of operational responsibility, so the decision should hinge on your team's willingness to host and patch a Node.js service.
Community notes