Strapi (Community Edition)
Strapi is a headless content management system built on Node.js. Its Community Edition is open-source and is installable as an npm package. Strapi is a popular option for Jamstack projects, according to the annual Jamstack Community Survey.
All content in Strapi is of a certain content-type, or a data schema definition. Content-types can be defined through the Strapi Admin panel. In there, Strapi also offers a CRUD interface to manage content and automatically generates REST API endpoints to access it—GraphQL is available via a plugin. By default, it's possible to enable draft & publish and internationalization for each content-type separately.
Strapi offers features outside of the standard data modelling and CRUD functionality.
Components Chunks of the data model can be grouped into components and reused across many content-types. A component can be added to a content-type as a singular field, as a list, or inside of a special Dynamic Zone field into which multiple components of different types can be added.
Plugins The building blocks of Strapi itself. Default plugins include the aforementioned Content Manager, Internationalization, Media Library and others. The user can install 3rd-party plugins via the Marketplace.
What we liked about Strapi is its simple design that allows for a wide range of use cases. Changing the data model in the Admin panel automatically generates the required changes in code, which can be then tracked in Git. This means that most of the data modelling can be done by a person with little to no coding experience. Custom API endpoints, middleware, and other customizations require coding, but boilerplate is limited to a minimum. It really feels like the team behind Strapi has put a lot of thought into file structure and seamless extensibility.
There are a few rough edges, though. For example, there is no way to have an abstract type from which to inherit other types. A similar result can be achieved via composition of components, but this creates unnecessary nesting of properties and has its limits when localization comes into play. In fact, we faced several issues related to localization, even though it's a built-in plugin. Strapi is also missing several obvious features like nesting of arbitrary components, which makes it very hard to e.g. dynamically change page layout for parts of the content.
Another hurdle is finding the necessary information in the documentation. It covers most use cases, but for those uncommon ones, your best bet is to consult the source code. For many customizations such as lifecycle hooks, you are expected to use global variables, which means no typing and help from the IDE. There were also cases of out-of-date sections on the official docs page.