How cmssy works
What lives in cmssy, what lives in your repo, and what happens between a request and a rendered page.
cmssy stores your content and never renders it. Your app renders your content and never stores it. Everything below follows from that one split.
What lives where
- In your repo - block schemas and components. A block is a React component plus a field schema, declared with
defineBlock. It is code: reviewed, versioned, deployed. - In cmssy - pages, block instances and their values, media, models and records, forms. It is data: edited visually or by an AI client, published without a deploy.
The line between them does not move. Adding a field means shipping code. Changing a headline does not.
What a page is
A page is a node in a tree. It has a slug derived from its parents, an ordered list of block instances that make up its body, and a layout - header and footer blocks it either owns or inherits from its parent.
Every block instance stores its values keyed by language, so content.en.title and content.de.title are the same field on the same block in two locales. There is no separate translated page.
From request to rendered page
A cmssy frontend needs one route. This is the whole of it:
// app/[[...path]]/page.tsx
import { createCmssyPage } from "@cmssy/next/server";
import { cmssy } from "@/cmssy/config";
import { blocks } from "@/cmssy/blocks";
export const revalidate = 3600;
export default createCmssyPage(cmssy, blocks);What happens when a request arrives:
- The catch-all route receives the path and turns it into a slug.
- The SDK asks the delivery API for the published page at that slug, plus its layout blocks. No token - published content is public.
- Each returned block instance carries a
type. The SDK looks that type up in the registry you passed as the second argument. - Your component renders with that instance's content for the active locale. Relation fields arrive already resolved to full records.
- A block type missing from your registry renders nothing on your site - and a diagnostic card naming the type when you open the editor. A block that throws, in its loader or its render, is contained the same way. Content cannot crash your app.
The registry is a plain array you maintain:
// cmssy/blocks.ts
import { heroBlock } from "@/blocks/hero/block";
import { pricingBlock } from "@/blocks/pricing/block";
export const blocks = [heroBlock, pricingBlock];The packages
The framework is an adapter, never the foundation:
@cmssy/core- transport, queries, config, the editor protocol. Zero framework. Runs in Node, on the edge, in a browser, in a cron job.@cmssy/react- rendering: block registry, components, the edit bridge, hooks.@cmssy/next- Next.js bindings only: middleware, route handlers,Metadata, sitemap and robots, page factories.
Adapters for other frameworks sit beside next, not on top of it, so an Astro or Remix app never installs React just to fetch a page.
@cmssy/next splits by runtime and the entries do not mix: @cmssy/next/middleware runs on the edge, /server in RSC and route handlers, /client in the browser.
Editing
Two ways in, one set of content.
The visual editor loads your real site in a frame and talks to it over postMessage. You edit the actual components, not a preview approximation - which is why the edit bridge lives in core rather than in the React package.
The MCP server gives an AI client the same write access: create pages, edit block content, upload media, publish. It edits content, never your code.
Drafts and publishing
Edits land in a draft. The public delivery API only ever returns published content, so an unfinished page is invisible to your site by construction - not by a filter you have to remember to apply.
To see drafts while developing, append ?cmssyDev=1 to any URL. It requires CMSSY_API_TOKEN and renders your own draft overlay; without the flag you get published content.
Publishing does not deploy. Your app caches pages according to its own revalidate value, and cmssy can call a revalidation webhook on publish to invalidate them sooner.
Next steps
- Installation - add the SDK to an existing Next.js app.
- Quickstart - first block and first page, end to end.
- Block development -
defineBlockand the field schema in depth. - API & AI - the delivery API and the MCP server.