BackmatterPricingDocs
Contents

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, and cms.query
  • path — where the file lives in your repo. {slug} is required unless singleton: true
  • route — the public URL, or false to keep the type off the site. Singletons default to false
  • singleton — at most one document
  • fields — 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.

KindHow you declare itGit filePublic URLQuery
Pagedefault route (or a custom template)content/{type}/{slug}catch-all mounts itcms.query.blog.get("hello")
Dataroute: falsesame as a collectionnonecms.query.people.get("mads")
Globalsingleton: true (route defaults to false)one filenone unless you set routecms.query.site.get()
ObjectdefineObject in objects/*.tsnone — embedded JSONnonenone
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 atMeaning
PublishedThe file as it is in the repo. Your site reads this.
Your editsChanges you have not published yet. The editor and preview show these first.
StatusMeaning
cleanYou have not changed the file. You see the published version.
modifiedYou changed a file that is already in the repo.
addedYou created a file that is not in the repo yet.
conflictThe repo changed, and you changed that file too.
  1. Open a document. You see your edits if you have any, otherwise the published file.
  2. Edit. Changes save as you go.
  3. Publish. One commit with your changed files, then your site can show them.
  4. 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

WhoWhat they see
You, in the editorYour edits, or the published file
Preview on your siteThe same, on the real page (live preview)
You, browsing the siteThe CMS editor, chat, and publish for that route (dev bar)
VisitorsThe published files