I’m excited to announce the release of my new open-source package: @fbritoferreira/strapi. This lightweight and generic TypeScript client is designed specifically for Strapi CMS v5, providing a streamlined, type-safe, and developer-friendly way to interact with Strapi APIs.
Why I Created This Package
While working extensively with Strapi in TypeScript environments, I noticed how repetitive and error-prone it was to handle API requests, particularly when dealing with complex filters, populating relations, pagination, localization (i18n), and error handling. Existing clients often lacked full TypeScript support or introduced unnecessary dependencies, which didn't fit well with lightweight projects.
This led me to build a minimal, modern client that uses native ES modules and Fetch API, prioritizing strong typing and ease of use. One key enhancement I contributed is the upsert functionality, an atomic create-or-update operation based on query filters. This feature simplifies synchronizing content, making workflows smoother by automatically creating an entry if it doesn’t exist or updating it if it does, without extra network calls or complex client-side logic.
Key Features
- Full TypeScript support: Define entity types for accurate request/response typing.
- CRUD operations: Standardized methods like findMany, find, create, update, and delete.
- Upsert operations: Simplify data synchronization with atomic create-or-update based on filters.
- Advanced querying: Supports Strapi filters, population, pagination, and locale selection.
- Internationalization support: Automated handling and linking of localized data.
- Minimal dependencies: Only uses a small query-string serializer alongside native APIs.
- Clear error handling: Async operations return [error, data] tuples for simpler coding.
Example Usage
Install the client easily:
npm install @fbritoferreira/strapi
Use it in your project:
import { StrapiClient } from "@fbritoferreira/strapi"; interface Article { id: number; title: string; content: string; } const client = new StrapiClient<Article>( "https://your-strapi-instance.com", "your-jwt-token", "articles", ); async function fetchArticles() { const [error, articles] = await client.findMany({ populate: ["*"] }); if (!error && articles) { console.log("Fetched articles:", articles); } } // Upsert an article (create if not exists, update if exists) async function upsertArticle() { const payload = { data: { title: "Hello World", content: "This is a test" } }; const filters = { title: { $eq: "Hello World" } }; const [err, article] = await client.upsert({ payload, filters }); if (!err && article) { console.log("Upsert successful:", article); } }
Contribute & Learn More
The package is fully open-source and actively maintained. Contributions, feature requests, and issues are welcome!
Check out the repository and get started:
https://github.com/fbritoferreira/strapi
I’m thrilled to provide this tool to the developer community to accelerate building scalable, type-safe content-driven apps with Strapi and TypeScript.
Happy coding!