In this article, we compare TypeScript support across three popular Headless CMS platforms: Strapi, Contentful, and Flotiq. We will examine their strengths and limitations, focusing on developer experience, integration complexity, and maintenance concerns.
As TypeScript adoption continues to grow in modern web development, developers are increasingly seeking Headless CMS platforms that integrate seamlessly with TypeScript. TypeScript enhances productivity with features like static typing, type inference, and code autocompletion, while reducing errors in development workflows.
When building with Next.js, choosing a CMS with strong TypeScript support and TypeScript resources can significantly streamline development. In this comparison, we analyzed three popular Headless CMS platforms: Strapi, Contentful, and Flotiq. We examined their strengths and limitations, focusing on developer experience, integration complexity, and maintenance concerns. For each of these solutions - we looked through the official documentation and available tutorials and examples, to find out how to make it work with Typescript.
Let’s dive into the details!
Strapi is a popular open-source Headless CMS known for its flexibility and self-hosting capabilities. It provides a REST API and optional GraphQL support, making it a versatile choice for developers.
First you need to create Content-Types which you plan to use:
Once you define the data model, content editors can immediately start their content management work using the generated forms (this is true only for the Strapi Cloud version). If self-hosting, additional steps are required: you must deploy Strapi to a publicly accessible server and configure appropriate access permissions for editors to interact with the system. This means you need to have devops/dbaAdmin engineers available in your organisation.
The development team gets access to the generated REST API, which reflects the data model. Specific endpoints allow access to different types of data, which is natural for developers with experience in RESTful APIs:
curl localhost:1337/api/products -H "Authorization:bearer $STRAPI_TOKEN"
This request queries the products API for all objects and produces a response similar to this:
{
"data": [
{
"id": 1,
"attributes": {
"Name": "Test",
"enabled": true,
"createdAt": "2023-12-08T08:26:17.828Z",
"updatedAt": "2025-01-06T18:58:33.421Z",
"publishedAt": "2025-01-06T18:58:33.420Z",
"locale": "en",
"description": null,
"price": null
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
The standard way of accessing the Strapi API in a Typescript project, as shown in Strapi tutorials (see links [1], [2], [3], [4], [5]), requires manual setup of interfaces for the IDE to understand the data model, so you can utilize the advantages offered by Typescript:
Once you define these interfaces, the IDE will start suggesting proper attributes and Typescript will verify type correctness:
Unfortunately, hand-crafting these interfaces is error-prone, tedious, and not suited for long-term maintenance as any change in the data model will have to be manually adjusted in the interfaces.
For those with direct access to the Strapi backend project, you can access type definitions generated by Strapi. Deep down in the file, you can find interfaces for all content types. You can import these files into the client/frontend project, but there are some caveats:
With that, you can finally utilize Typescript in the client application:
Note how the IDE autocompletes the property names available in the Product content type.
Unfortunately, some additional concerns arise:
This can easily happen when the project is in maintenance mode and updates are needed without access to the development team. It's also common in large enterprise builds, where separate teams are responsible for maintaining the CMS backend and building client frontend applications.
The Strapi community understands this problem and has come up with solutions based on either OpenAPI or GraphQL (both carry type information), but these solutions are not exactly out-of-the-box or trivial to use.
The OpenAPI approach has been thoroughly described on the Strapi Blog and, although quite complex, it offers a good and standards-based solution to the problem.
However, the GraphQL-based setup (which should be simpler) is only referenced in a Strapi forum thread from 2021:
But since the dotansimha/graphql-code-generator library is hugely popular, this approach is likely to be successful.
Contentful is a cloud-hosted Headless CMS, known for its intuitive content editor interface and robust API options (GraphQL and REST).
In order to compare with Strapi and Flotiq - we start with the same content-type built in Contentful:
Once you define the model, content editors get a graphical interface to enter content:
Developers have access to generic Contentful GraphQL and REST APIs, like this:
It's easy to see that the API described in Contentful docs is not very friendly to use. Strapi and Flotiq have an easier way of accessing content, where API endpoints reflect the content types which are created in your account.
Contentful publishes an interesting blog post, highest ranking for "contentful nextjs typescript", How to use TypeScript in your Next.js project. Unfortunately, the post seems mainly SEO-oriented and only briefly mentions how Typescript, Contentful, and Next.js can improve developer experience:
Not very useful.
The official Contentful + next.js starter does not seem to provide any support for Typescript on the content management side of things, either. Furthermore, it uses hardcoded GraphQL queries and content models to fetch the data:
As indicated by the wide use of the any TS type, it does not support any integration with the IDE:
A blog post by Max Schmitt is an improvement, as it shows how adding hand-crafted Typescript interfaces to the code can provide TS support:
The contentful.js v10 announcement promised improved Typescript support, but manually created interfaces can still be seen in the demo code.
Fortunately, when digging deeper into the contentful.js SDK, the Typescript readme file provides a list of 3rd party open-source packages that can help with type generation.
Out of 4 packages, only 2 seem noteworthy.
Using the intercom/contentful-typescript-codegen package (most starred among the 4 packages listed by Contentful) actually yields promising results, including type information on individual fields:
However, you still need to manually edit the GraphQL query.
To get around this, you can use the contentful.sdk, which should be able to understand the data model in the Contentful account. Unfortunately, it turns out that types generated from the Intercom package do not support the Skeleton types used by the official Contentful SDK.
Although the contentful-userland/cf-content-types-generator package seems to be less popular than the Intercom one, it seems to provide better compatibility with the Contentful Typescript SDK.
After running
yarn add cf-content-types-generator
the package is installed and ready to generate types compatible with the current Contentful SDK
yarn run cf-content-types-generator -s $CONTENTFUL_SPACE_ID -t $CONTENTFUL_MANAGEMENT_ACCESS_TOKEN --out @types --response -X
This produces a clean set of type definitions, like this one:
… so much better than what was obtained with Strapi.
With this in place, the IDE is finally ready to work with Typescript and Contentful:
Contentful offers partial TypeScript support through third-party tools, but the integration process is cumbersome. The basic setup relies on manually crafted GraphQL queries and and hardcoded interfaces, which limits its appeal for TypeScript-driven workflows. On the other hand, when fully setup with the 3rd party tools - Contentful offers a better experience than Strapi, it also allows content editors to start working immediately after the content types are setup.
Flotiq stands out for its simplicity, developer-first design, and comprehensive tools for content editors and developers.
Adding a content type definition in Flotiq is very similar to the process seen in Contentful or Strapi.
When you define the model, as with any other headless CMS, content editors working with Flotiq can start creating content using an easy-to-use form:
Similar to other cloud-hosted systems, like Contentful or Strapi Cloud, Flotiq provides the editors with immediate access to data. Self-hosted systems, in contrast, require a significant (sometimes) effort to deploy and host the system in a way that it’s available to the entire team.
What makes Flotiq stand out, compared to Contentful and Strapi, is the amount of options and easy-to-use tools it gives to the development team:
You can find more about these features in the Flotiq developer documentation.
Flotiq’s native support for OpenAPI makes it easy to generate client code for different languages - Java, Python, Dart (for Flutter), Typescript and several more. The Typescript SDK has received much love in the recent months and provides the easiest and most comprehensive method of accessing CMS content among all compared systems.
Install the flotiq/flotiq-codegen-ts sdk
npx flotiq-codegen-ts generate
During the installation you will be asked to provide your Flotiq API key and a few seconds later - the types will be generated. The resulting integration is, by far, the easiest to use and provides full support for types on all attributes in your content model:
This level of integration provides developers with the best most convenient access to the data stored in their CMS.
Choosing the right Headless CMS for your Next.js project depends on your priorities. Here’s a quick summary of TypeScript CMS support with our ranging, from most compatible to lowest compatible:
1. Flotiq
2. Contentful
3. Strapi