
Strapi Expert
Ship or refactor Strapi v5 plugins, content-types, and custom APIs using Document Service patterns instead of deprecated Entity Service code.
Overview
Strapi Expert is an agent skill for the Build phase that guides Strapi v5 plugin development, custom APIs, and CMS architecture using the Document Service API.
Install
npx skills add https://github.com/mkshahzad77/claude-skill-strapi-expert --skill strapi-expertWhat is this skill?
- Mandates Strapi v5 Document Service API (`strapi.documents`) for all CRUD instead of deprecated Entity Service
- Covers plugin structure, custom APIs, admin panel extensions, and content-type creation
- Maps v4 Entity Service calls to v5 Document Service equivalents in a reference table
- Troubleshooting and best-practice guidance for production-grade Strapi v5 plugins
- Triggered by Strapi terms: content-types, controllers, services, routes, plugin structure
- Document Service vs Entity Service reference table for findMany, findOne, create, and update operations
Adoption & trust: 997 installs on skills.sh; 3 GitHub stars; 1/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are on Strapi v5 but your agent still emits Entity Service patterns, brittle plugins, or unclear content-type and route structure.
Who is it for?
Indie builders shipping or refactoring a Strapi v5 headless CMS, custom plugins, or Document Service–backed APIs.
Skip if: Teams not using Strapi, greenfield apps with no CMS, or front-only work with no backend plugin changes.
When should I use this skill?
Working with Strapi v5 backend development, building or refactoring plugins, Document Service API usage, content-types, or Strapi-specific troubleshooting.
What do I get? / Deliverables
You get v5-aligned plugins and APIs centered on `strapi.documents`, with clearer controllers, services, and admin extensions ready to extend.
- Strapi v5 plugin or API code using Document Service patterns
- Content-type, controller, service, and route structures aligned with v5 conventions
- Refactored modules with Entity Service usage removed or migrated
Recommended Skills
Journey fit
Headless CMS and plugin work happens while building the product backend and admin extensions, not during early idea research. Strapi controllers, services, routes, and `strapi.documents` usage are core backend/CMS architecture tasks in the build phase.
How it compares
Use this as a Strapi v5 procedure pack—not a generic REST backend skill or an MCP server integration.
Common Questions / FAQ
Who is strapi-expert for?
Solo and indie builders using Strapi v5 for plugins, content-types, custom APIs, and CMS architecture who want agent output to follow official v5 conventions.
When should I use strapi-expert?
During Build when you are creating or refactoring Strapi plugins, implementing Document Service CRUD, extending the admin panel, or troubleshooting Strapi-specific controller, service, and route issues.
Is strapi-expert safe to install?
It is allowed to read, write, edit, bash, and fetch the web; review the Security Audits panel on this Prism page and restrict secrets before running commands in your repo.
SKILL.md
READMESKILL.md - Strapi Expert
# Strapi v5 Expert You are an expert Strapi v5 developer specializing in plugin development, custom APIs, and CMS architecture. Your mission is to write production-grade Strapi v5 code following official conventions and best practices. ## Core Mandate: Document Service API First In Strapi v5, **always use the Document Service API** (`strapi.documents`) for all data operations. The Entity Service API from v4 is deprecated. ### Document Service vs Entity Service | Operation | Document Service (v5) | Entity Service (deprecated) | |-----------|----------------------|----------------------------| | Find many | `strapi.documents('api::article.article').findMany()` | `strapi.entityService.findMany()` | | Find one | `strapi.documents(uid).findOne({ documentId })` | `strapi.entityService.findOne()` | | Create | `strapi.documents(uid).create({ data })` | `strapi.entityService.create()` | | Update | `strapi.documents(uid).update({ documentId, data })` | `strapi.entityService.update()` | | Delete | `strapi.documents(uid).delete({ documentId })` | `strapi.entityService.delete()` | | Publish | `strapi.documents(uid).publish({ documentId })` | N/A | | Unpublish | `strapi.documents(uid).unpublish({ documentId })` | N/A | ### Basic Document Service Usage ```typescript // In a service or controller const articles = await strapi.documents('api::article.article').findMany({ filters: { publishedAt: { $notNull: true } }, populate: ['author', 'categories'], locale: 'en', status: 'published', // 'draft' | 'published' }); // Create with draft/publish support const newArticle = await strapi.documents('api::article.article').create({ data: { title: 'My Article', content: 'Content here...', }, status: 'draft', // Creates as draft }); // Publish a draft await strapi.documents('api::article.article').publish({ documentId: newArticle.documentId, }); ``` ## Plugin Structure A Strapi v5 plugin follows this structure: ``` my-plugin/ ├── package.json # Must have strapi.kind: "plugin" ├── strapi-server.js # Server entry point ├── strapi-admin.js # Admin entry point ├── server/ │ └── src/ │ ├── index.ts # Main server export │ ├── register.ts # Plugin registration │ ├── bootstrap.ts # Bootstrap logic │ ├── destroy.ts # Cleanup logic │ ├── config/ │ │ └── index.ts # Default config │ ├── content-types/ │ │ └── my-type/ │ │ └── schema.json │ ├── controllers/ │ │ └── index.ts │ ├── routes/ │ │ └── index.ts │ ├── services/ │ │ └── index.ts │ ├── policies/ │ │ └── index.ts │ └── middlewares/ │ └── index.ts └── admin/ └── src/ ├── index.tsx # Admin entry ├── pages/ ├── components/ └── translations/ ``` ### Package.json Requirements ```json { "name": "my-plugin", "version": "1.0.0", "strapi": { "kind": "plugin", "name": "my-plugin", "displayName": "My Plugin" } } ``` ## Routes Definition ### Content API Routes (Public/Authenticated) ```typescript // server/src/routes/index.ts export default { 'content-api': { type: 'content-api', routes: [ { method: 'GET', path: '/items', handler: 'item.findMany', config: { policies: [], auth: fa