BackmatterPricingDocs
Contents

API

The client your site calls, and the tokens it uses.

Your pages call cms. The keys on a model are Fields. A Next.js app turns a document into a URL in Next.js.

The client

import { cms } from "backmatter";

await cms.listDocs({ type: "blog" });
await cms.query.blog.get(slug); // null when the file is missing

workspaceId and the API URL come from backmatter.config.ts. Tokens stay in the environment: BACKMATTER_API_URL, BACKMATTER_CONTENT_TOKEN, BACKMATTER_PREVIEW_TOKEN. Without the API URL and content token, cms reads content/ from disk.

Typed query

const post = await cms.query.blog.get(slug);                 // TypedDoc | null
post?.frontmatter.title;                                     // string (required field)

const posts = await cms.query.blog.findMany({
  where: { featured: true },        // equality on slug, text, number, boolean
  include: { authors: true },       // depth 1; missing → null
});
posts[0]?.authors?.frontmatter.name;

Keys are model.type. A relation is the other document's slug in frontmatter. Querying is the full language.

cms.query trusts the file. Run backmatter validate in CI for files in the repo. Publish checks documents saved in the CMS. Renaming a field in models/blog.ts is a type error wherever you use cms.query.blog. A content file only fails validation when a new field is required.

Validate before push

bunx backmatter validate      # models from models/*.ts; exit 1 on invalid frontmatter
bunx backmatter schema        # .backmatter/schemas/{type}.json
bunx backmatter generate      # .backmatter/* registry (withBackmatter does this for you)

withBackmatter already rewrites .backmatter/ when the Next app compiles. Run generate yourself in CI or outside Next.

validate reads models/*.ts and the folders in each model's path. It does not walk the rest of the repo. A required field that is missing fails the command. Unknown frontmatter keys are kept.

Auth for content

TokenUse
BACKMATTER_CONTENT_TOKENPublished documents on the public site
BACKMATTER_PREVIEW_TOKENThe unsaved copy on preview

The content token is for your site's published reads. The preview token is for the preview page. Neither is the login cookie for the CMS.