Open-source headless CMS
Model → API.
No restart.
Shapio is a self-hosted headless CMS whose content models change in production with no rebuild or restart, and whose schema lives in git as well as in the admin. Schema and content ship together in reviewed change sets, and editors get tools that are finished.
Models change live, schema and content ship together as snapshots, and agents propose while people ship.
Model
page · schema v14 · active
REST · GraphQL
served from the model
Editors
rich text · media · relations
Ship
change set → snapshot 214
Webhooks
signed · retried
Build
triggered → building → deployed
Your site
deployed ✓
Live modelling
Add a field in production. It's live. That's the whole feature.
Models are versioned rows in your database, not files in your repo. Adding a field, renaming a label or switching an editor activates a new schema version in one transaction, at once with Ship now or together with a change set. No dev mode, no rebuild, no PM2 restart, no downtime.
- Required fields are validated or backfilled before they go live
- Stable IDs: renaming a label never touches data
- Two admins editing the same model: one wins, the other sees the conflict
Schema in git · Change sets
Ship like code: pull, review, ship, restore.
Models export to JSON files with stable IDs and apply live from CI: changes made in the admin since your pull are kept, and a model changed on both sides is refused with both shown, like a rejected push. In the admin, a change set groups schema edits and entry drafts, is reviewed like a pull request, and ships as one numbered snapshot, so a site never sees a new field without the entries that use it. Restoring an older snapshot opens a new change set: nothing is deleted, and the schema is not rolled back.
- #214Change set · Autumn launchschema v18 · 23 entrieslivedeployed
- #213Publish · Pricing (fr)schema v17 · 1 entryRestore
- #212Restore of snapshot 209schema v17 · 4 entriesRestore
Every snapshot stays readable, and ?snapshot=N pins a build to one moment.
Editors that ship finished
Rich text, media, relations and components. In the box, done properly.
A field's data type is separate from how it's edited, so you can swap a toggle for a segmented control without touching data. Every control works with a keyboard, shows its errors inline and protects unsaved edits. Custom React editors get the same server validation as everything else.
- Rich text with tables
- Repeatable components
- Dynamic zones
- Relation picker
- Media library
- Localized fields
- Custom React editors
Visual editing and preview
The draft renders on your real site beside the document: click a heading or an image to focus its field, and every save re-renders the page. Sites mark their fields with @shapio/visual, the Astro, Next.js and SvelteKit starters come set up, and the admin only frames the preview sites you connected. Preview tokens last an hour and cover one entry and locale.
- Astro
- Next.js
- SvelteKit
- @shapio/visual

Assist and MCP
Agents propose, people ship.
Assist uses your own model provider, hosted or running on your machine, for alt text, summaries, translations, rewrites, content-type drafts and fixes for missing alt text and locales. It is off by default, and while it is off nothing leaves your server. Every result is a field you review or a draft in a change set.
With npx -y @shapio/mcp, an agent in any MCP client models content types, writes entries and opens a change set for review. It cannot ship unless you pass --allow-ship and its role holds changes.ship.
- schema_draft menuItem → change set "Spring menu"
- content_create ×6 → 6 drafts
- change_sets_add_entry ×6 → "Spring menu"
- change_sets_review → 0 blocking · 1 warning
- change_sets_ship ✗ 403 FORBIDDENYour role does not allow changes.ship
- Change planner dry run: nothing to convert
- 6 entries validate against the schema they ship with
- 1 warning: an image without alt text
- No breaking changes
Also in the box
The things other CMSs put behind an enterprise plan.
REST and GraphQL serve every model from the active schema with the same filters, sorting, paging, population and field selection, and public delivery only ever sees published content.
Many sites
One schema and one login. Each site has its own content, media, tokens, snapshots, change sets and app users.
Roles and audit log
Roles per model, action and field, on one site or all sites. An audit log of who changed what, agents included.
History and scheduling
Every save is a revision you can restore. Ship a change set, or publish one entry, at a set time.
Localization
Localized and shared fields, fallback chains, publishing per locale.
End-user accounts
Sign-up, Google and GitHub sign-in, roles, owner-only writes. Your app's users, per site.
Deployments and webhooks
Cloudflare Pages, Vercel, Netlify or a signed build hook, with real build status and retry. Webhooks are signed and retried.
Content health and usage
An Inbox of images without alt text and missing locales, and which tokens read which fields before a breaking change ships.
Media
Local disk or S3 and R2, private files with signed URLs, WebP variants.
Site starters
Astro, Next.js or SvelteKit, from create-shapio: a blog in two languages, seeded live, with preview and visual editing.
Importers
WordPress (WXR) and Strapi 5 exports become schema files to apply, then drafts. What was published lands in a change set.
Export and import
Content and media bundles with a dry-run plan. Imports keep IDs and resume.
Tokens, types, extensions
Scoped delivery tokens, OpenAPI and TypeScript types from the active schema, and hooks, routes and jobs loaded at runtime.
FAQ
Questions
Does changing a model need a rebuild?
No. A model change activates a new schema version in the running server, and REST and GraphQL serve it on the next request; only environment variables, code extensions and upgrading Shapio itself need a restart.
Which databases does it run on?
PostgreSQL 16 or later, or SQLite. Use PostgreSQL for several instances, a separate worker or many editors writing at once, and move from SQLite to PostgreSQL later with export and import.
Do I need the AI assist?
No. Assist is off until you set AI_PROVIDER, and while it is off nothing leaves your server; when you turn it on, it uses your own model provider, hosted or running on your machine.
Can I run it free on one small server?
Yes: every feature is in the Apache-2.0 core, and with SQLite the whole instance is one Node process and one database file. Keep that file on a persistent local disk, not a network file system, and back it up with shapio backup while Shapio runs.
How do I move from WordPress or Strapi?
shapio import wordpress or shapio import strapi reads a WXR or Strapi 5 export and writes schema files you review and apply live. A second step uploads the media and creates every entry as a draft, with the ones published at the source in a change set you review and ship.
What is the licence?
Apache-2.0, for the server, the admin and the packages. There is no hosted account and no telemetry: Shapio sends nothing anywhere unless you configure it.
Running in two minutes, your way.
One Node process and PostgreSQL or SQLite. Run it with npm and PM2, or with Docker. Both paths are first-class and get the same admin, API and live modelling.
- npm + PM2npx create-shapio@latest my-cms --database-url sqlite:./shapio.dbcd my-cms && pm2 start ecosystem.config.cjs✓ http://localhost:4300 · open /admin/ to create the owner
- Dockercurl -O https://raw.githubusercontent.com/mybrokengnome/shapio/main/docker-compose.ymldocker compose up -d✓ shapio + postgres on :4300 · open /admin/ to create the owner