"projectsShipped": {
"type": "integer",
"min": 32,
"required": true
}
Stack Innovations
Start a project
Most Strapi projects ship the default admin and a public REST endpoint.
We treat Strapi as code — schema.json, custom
controllers, lifecycle hooks, RBAC
policies, dynamic zones tuned for editors, GraphQL on
when it should be. Headless content with a head your team will fight
to use.
Each stat is a Strapi attribute. Hover any to see the JSON it'd ship as in schema.json — counters scrub with scroll, validations enforced, anime.js staggers the reveal.
"projectsShipped": {
"type": "integer",
"min": 32,
"required": true
}
"contentTypesModeled": {
"type": "integer",
"min": 1840,
"required": true
}
"customControllers": {
"type": "integer",
"min": 210,
"default": 0
}
"defaultBuilds": {
"type": "integer",
"max": 0,
"default": 0
}
Click the sidebar on the left — the active capability opens in the Content Manager, rendered as a real Strapi entry edit screen. Each pane is a working schema we've shipped.
Content-Type Builder, used like a tool, not a screen.
We model collection types and single types like database tables — with foreign keys, validations, indexes — not by clicking through field pickers. Schemas live in src/api/*/content-types/*/schema.json, version-controlled, code-reviewed.
min, max, regex, customStrapi's signature feature is the Dynamic Zone — an array of components, picked at edit time. We design the component library, lock the type signatures, and ship a renderer per surface. Editors compose pages, not posts.
type: 'dynamiczone'Strapi auto-generates REST and GraphQL from your schema. We pick the right one per surface, custom-controller the slow paths, layer field-level populate and fields filters, and put a CDN in front of it.
extended corefields=...&populate=...Strapi ships RBAC. We tune it — field-level conditions, route policies, custom auth providers, scoped admin views. Editors see what they need, never what they don't.
policies/is-owner.jsbeforeCreate, afterUpdate, beforeDelete. Strapi's lifecycle hooks are where slug generation, search indexing, webhook fan-out, audit logging, and cache invalidation belong — not in your frontend.
From WordPress, Contentful, Sanity, Drupal, or that homegrown CMS no one wants to touch. We model the schema first, write Knex migrations as reversible scripts, run them against a staging dataset, and cut over with redirects mapped.
This is what makes Strapi itself: schemas are the API. Drag any field type from the palette onto the schema — the REST and GraphQL responses on the right rebuild in real time. anime.js draggable, popmotion inertia, mojs burst on save.
Same platform, two article.controller.ts files. The diff tells the story.
import { factories } from '@strapi/strapi' export default factories.createCoreController( 'api::article.article' ) // no auth tuning // no field filtering // no rate-limit policy // no audit log // no error envelope // shipped to prod — everywhere.
import { factories } from '@strapi/strapi' import { audit } from '../../../policies/audit' import { rateLimit } from '../../../policies/rate' export default factories.createCoreController( 'api::article.article', ({ strapi }) => ({ async find(ctx) { await rateLimit(ctx, { rpm: 60 }) const { results, pagination } = await strapi.service('api::article.article') .findScoped(ctx.state.user, ctx.query) audit(ctx, 'article.read', results.length) return this.transformResponse(results, { pagination }) }, async create(ctx) { ctx.assertOwner() const out = await super.create(ctx) strapi.lifecycles.emit('article.created', out) return out }, }))
Dynamic Zones are Strapi's signature feature — an array of components, picked by an editor at runtime. Drag the blocks on the left to reorder, click the + to insert a component, watch the rendered preview rebuild on the right with popmotion inertia.
blocks
Audit the existing CMS, model collection types and components, lock the editor experience as a deliverable.
Strapi v5 scaffolded, schemas in JSON, environments configured (production / staging / dev), Postgres bootstrapped.
Custom controllers, lifecycle hooks, components & dynamic zones, custom admin inputs, RBAC tuned.
Knex migrations (reversible), staging dry-runs. Sitemaps, redirects, hreflang, schema markup.
Loom walkthroughs, role setup, dry-run publishes. DNS cutover. Slack handoff.
Schema upkeep, Strapi version bumps, perf monitoring, monthly review. Features, not tickets.