nextjs-cms

Writing Docs

How this documentation site is built, how to add a page, and the style every page follows.

This site lives in apps/docs. It's a Next.js app that renders MDX files from content/ at build time.

Terminal
pnpm --filter docs dev   # http://localhost:3001

Two audiences, two trees

AreaURLFolderAudience
Using nextjs-cms/docscontent/docs/Developers building a CMS
Contributing/contributingcontent/contributing/People changing nextjs-cms

Never mix them. A developer page shouldn't explain SectionFactory; a contributor page shouldn't re-teach textField options. Link across instead.

Adding a page

  1. Create the MDX file. The path is the URL: content/docs/guides/caching.mdx → /docs/guides/caching. A folder's landing page is index.mdx.

  2. Add frontmatter:

    ---
    title: Caching
    description: One sentence shown under the title, in search results, and in the page metadata.
    ---
  3. Register it in lib/navigation.ts. The sidebar, breadcrumbs, previous/next links, search index, and static generation all come from that file. A page that isn't in the navigation isn't built.

Components

Available in every MDX file without importing:

Code blocks

Fenced code with Shiki highlighting. Meta options:

```ts title="sections/posts.section.ts" {3,5-7} showLineNumbers
// title: shown in the header bar
// {3,5-7}: highlighted lines
// showLineNumbers: line numbers
```

bash blocks get a "Terminal" header automatically. Languages: ts, tsx, js, jsx, json, bash, sql, diff, txt, css, yaml, markdown, mdx.

Callout

<Callout>A note ("Good to know").</Callout>
<Callout type="tip">A shortcut or best practice.</Callout>
<Callout type="warning">Something that can bite.</Callout>
<Callout type="danger">Data loss or security.</Callout>
<Callout type="warning" title="Known issue">Custom label.</Callout>

Tabs

<Tabs items={['pnpm', 'npm']} groupId="package-manager">
<Tab>
```bash
pnpm add nextjs-cms
```
</Tab>
<Tab>
```bash
npm install nextjs-cms
```
</Tab>
</Tabs>

Tabs sharing a groupId switch together and remember the choice.

Cards

<Cards>
  <Card href="/docs/fields" title="Fields">Short description.</Card>
</Cards>

Writing a field page

Every field page follows the same structure, so readers know where to look:

  1. Import line.
  2. Basic usage: the smallest working config, usually just name.
  3. With every option: one example using all options.
  4. Options table: option, type, default, description. Link to the common options instead of repeating them.
  5. Options in detail: one subsection per option that needs more than a table cell, each with an example.
  6. Examples: realistic scenarios.
  7. Storage: the column type and the stored value format.

Section pages follow a similar pattern: when to use it, minimal example, options, then one example per scenario.

Style

  • Verify against the source. Every option, default, and behavior must match the code. When the code doesn't implement something yet, say so ("Reserved") rather than describing the intent.
  • Lead with the example. Show code first, explain after.
  • Complete examples. Imports included when they aren't obvious; examples should work if pasted.
  • Plain language. Short sentences, active voice, second person ("you"). Avoid "simply" and "just".
  • One idea per heading. Headings become the "On this page" navigation and search entries.
  • Link generously between related pages, using root-relative URLs (/docs/fields/select).

Before you open a PR

Terminal
pnpm --filter docs exec next build

The build compiles every MDX page, so syntax errors (an unclosed JSX tag, a stray < in prose) fail it.