Content
Documents, draft versus published, and where files live.
A document is a file in your repository. Editors change it in the CMS. Publish writes those changes back to the file as a commit. Your site reads the published files.
What a document is
A document is one file identified by { type, slug }. Slug is implicit index when a singleton omits {slug}.
That identity maps to a path via the model’s path template, e.g.:
content/blog/{slug}.mdx → content/blog/hello.mdx
content/people/{slug}.mdx → content/people/mads.mdx
content/site.json → content/site.json
Inside the file:
---
title: Hello
slug: hello
---
Body in Markdown / MDX…
- Frontmatter — structured fields from the model (
title, relations, …) - Body — MDX, rendered with your components in
blocks/
Content types are MDX documents. The model is what makes a file a document of that type.
Content types (models)
A type such as blog or people is a model file. You define it in the repo. The CMS builds its forms from that file.
The model declares:
type— the name you use in paths, URLs, andcms.querypath— where the file lives in your repo.{slug}is required unlesssingleton: trueroute— the public URL, orfalseto keep the type off the site. Singletons default tofalsesingleton— at most one documentfields— the frontmatter the editor fills in. Every kind is Fields
Reusable shapes (defineObject in objects/*.ts) are fields inside a document, not files of their own. How a page loads these files is Querying.
The editor groups models as Pages (they have a URL), Data (route: false), and Globals (singletons). Objects do not appear in that sidebar.
Pages, data, globals, objects
One primitive: defineModel. Flags and path placeholders change how the file is used.
| Kind | How you declare it | Git file | Public URL | Query |
|---|---|---|---|---|
| Page | default route (or a custom template) | content/{type}/{slug} | catch-all mounts it | cms.query.blog.get("hello") |
| Data | route: false | same as a collection | none | cms.query.people.get("mads") |
| Global | singleton: true (route defaults to false) | one file | none unless you set route | cms.query.site.get() |
| Object | defineObject in objects/*.ts | none — embedded JSON | none | none |
export default defineModel({
type: "people",
route: false,
path: "content/people/{slug}.mdx",
fields: { name: field.text({ required: true }) },
})
export default defineModel({
type: "navbar",
singleton: true,
format: "page",
path: "content/navbar.json",
fields: { items: field.array(navItem) },
})
export default defineObject({
name: "navItem",
fields: {
label: field.text({ required: true }),
href: field.text({ required: true }),
},
})
A type has a public URL when its model sets route.
Unsaved edits and published files
There is no separate draft type. If a page should stay off the site until it is ready, add a status field and filter on it in your app.
| What you are looking at | Meaning |
|---|---|
| Published | The file as it is in the repo. Your site reads this. |
| Your edits | Changes you have not published yet. The editor and preview show these first. |
| Status | Meaning |
|---|---|
clean | You have not changed the file. You see the published version. |
modified | You changed a file that is already in the repo. |
added | You created a file that is not in the repo yet. |
conflict | The repo changed, and you changed that file too. |
- Open a document. You see your edits if you have any, otherwise the published file.
- Edit. Changes save as you go.
- Publish. One commit with your changed files, then your site can show them.
- Conflict. Publish waits until you choose Keep mine or Take theirs.
Revert throws away your edits for that file and puts you back on the published version.
Changes from git
If someone commits to the repo outside the CMS, those files show up as the published version. Your own unsaved edits are left alone. If both sides changed the same file, it becomes a conflict. Pull from GitHub in the branch menu is there if a push did not show up.
Who sees what
| Who | What they see |
|---|---|
| You, in the editor | Your edits, or the published file |
| Preview on your site | The same, on the real page (live preview) |
| You, browsing the site | The CMS editor, chat, and publish for that route (dev bar) |
| Visitors | The published files |