Content

Content & data

Forms, models and records - the structured content behind your blocks.

Structured content

Models, records, media and forms - the data your blocks render, and how blocks reach it.

Pages are made of blocks, and blocks need data. Some of it lives inside the block instance itself - a heading, a paragraph, an image. The rest lives in structured collections you define once and reuse everywhere: models, records, media and forms.

Models and records

A model is a schema for a kind of content: a product, an author, a job posting, a case study. A record is one entry against that schema. Models live at workspace level, not on a page, so the same collection feeds as many pages and blocks as you like.

You define models in the workspace, not in your frontend code. That is the opposite of block schemas, which are code and ship with your repo - the split is deliberate: shape of the UI in code, shape of the data in cmssy.

Connecting records to blocks

Blocks pull records in through a relation field. A relation stores ids, not copies - the delivery API resolves them to full records at render time, so a record edited once updates everywhere it appears.

  • picked (the default) - the editor picks one record, or several with multiple: true. A featured case study; the three plans on a pricing page.
  • mode: "all" - the field stores nothing at all; the block receives every record in the model, shaped by sort and limit. Use it for a blog index or an FAQ that should never need re-curating.

This is why a "latest posts" block keeps working after you add a post: it holds a query, not a snapshot.

Media

Images and files live in the workspace media library, organised in folders. Blocks reference media by URL, and each upload gets its own hashed URL - so uploading a replacement does not update the blocks pointing at the old file. There is no in-place replace, so re-pointing the blocks is the remedy: a search-and-replace over block content, which is exactly what the MCP server is good at. Uploads, folders and moves are all available through the MCP server, which makes bulk media work scriptable.

Forms

Forms are built visually in the workspace and rendered by whichever block you attach them to. Submissions land back in cmssy, where each one carries a status you can move through your own workflow.

Submission is the one write your public frontend can perform without a token - it goes through the form.submit mutation on the delivery API. Everything else about forms - creating them, reading submissions, changing status - requires an authorized client.

Everything is multilingual

Every field is multilingual by default. Content is stored keyed by language code, so one record carries all its translations and the delivery API hands your frontend the right one for the active locale. You do not model translations - you fill them in.