Documentation templates
Twelve page kinds, each with a fixed set of headings the build enforces. The outlines are published verbatim, so a contributor fills in a template.
The short version
A page's kind fully determines its headings. Authors do not invent
sections, do not reorder them, and do not leave one empty. assert-ia compares
the H2s in every page against the outline for its kind and fails the build on a
missing or an unexpected one.
That sounds heavy-handed and it is the reason four hundred pages stay navigable. A reader who has read one health page knows where the boundary statement is on every other one; an agent that has parsed one component page knows where the prohibition list lives on all sixty.
The templates themselves live in apps/www/content/_templates/. There is one
.mdx per kind, kept outside content/docs/ so they are never routed. Copy
one; do not start from a blank file.
How it works
Twelve kinds. The outlines are reproduced here verbatim, in order. Where a section is generated, it is marked.
component
The lean anatomy, taught once on Anatomy of a component
page. <StubNotice> opens
the page above the first H2, and there is no Status heading. The sections that
render are gated by status: at planned the page shows Preview,
Installation, When to use it, Clinical meaning (health-* only), Anatomy
(optional), Proposed API, Accessibility and Related. shipped adds Usage,
Examples and API reference, and may also carry States, Content guidelines, Data
attributes and CSS variables where there is something to say. deprecated owes
the same outline as shipped. Sections not required at the declared status are
omitted, not left empty, and the body is held to a thousand words, or twelve
hundred and fifty on a health-* page.
foundation
## Overview → ## How it works → ## Using it → ## Tokens (generated) →
## Accessibility impact → ## Related
health
## What this means → ## The rule → ## Why (evidence) → ## Applying it →
## Components that implement this (generated from implements) →
## What this does not cover → ## Updates to this page
evidence and reviewed are mandatory frontmatter on this kind.
accessibility
## What we guarantee → ## What you own → ## How to check →
## Measured results (generated) → ## Known gaps →
## Updates to this page
content
## The rule → ## Approved / Rejected → ## Patterns → ## Banned words →
## Related components
pattern
## When to use → ## When not to use → ## How it works → ## Content →
## Accessibility → ## Research → ## Updates to this page
Every entry under "when not to use" names the alternative.
recipe
## The task → ## What you need → ## Build it → ## The copy →
## Get it right → ## Variations → ## Related
screen
## What this screen does → ## Composition → ## Preview →
## Safety notes → ## Accessibility → ## Status
handbook
## The short version → ## How it works → ## Do this → ## Not this →
## Gotchas → ## Related
This page is one.
reference
Generated body only, plus a hand-written header block naming the source file and the script that produces it.
project
Free-form headings, but every page ends with <LastUpdated /> and
<Reviewed />.
guide
## Overview → one H2 per task, named by the author → ## Verify it worked →
## Troubleshooting → ## Next
The four fixed sections and their order are the contract; the task sections in between are yours.
Do this
- Copy the template file for your kind.
content/_templates/<kind>.mdx. - Fill every section. On every kind but
component, a section with one sentence under it is a signal that either the page or the kind is wrong. On a component page one sentence is often the whole answer. - Use
<Todo>for a genuine gap. It is counted in the build's coverage report, which is the point: incompleteness is measured rather than hidden. - Use the closed MDX vocabulary. The tags listed in the component anatomy
are the only ones that exist;
assert-iafails the build on an unknown JSX tag, and content authors never define one. - Write relative links with the
.mdxextension.[Two colour axes](../../health/two-colour-axes.mdx). fumadocs'createRelativeLinkresolves them. - Write a related-links bullet as a sentence. The linked page or the bold
term is the subject, and the verb comes from a closed table. A page that is
the thing its gloss names takes
is, a page that holds the thing takeshas, and where neither reads true the verb iscovers. A gloss opening withwhat,which,whetherorwhentakessays. One opening withwheretakesis where, which absorbs thewhereout of the gloss.whytakesexplains,howtakesshows, and any other bare noun phrase takescovers. A gloss that already opens with a finite verb or a modal takes no added verb at all. Where the gloss is not a predicate of the link, give the link a short predicate of its own and put the gloss into a second sentence. The link text stays the page title, the gloss keeps its wording and its lower-case first letter, the item ends in a full stop, and no colon stands between the link and its gloss.
Not this
- Do not add a heading the outline does not have, however good it is. If a kind genuinely needs a new section, change the kind's outline in one place and every page that uses it.
- Do not leave a required section empty to satisfy the check. An empty
section is a worse answer than
<Todo>, because<Todo>is counted. - Do not use an absolute site link in MDX. Write a relative file link and
let fumadocs resolve it. There is no exception left: the one that used to
exist, the Sections rail in the root
meta.json, was deleted with the rail. - Do not restate a canonical page.
Plain-English A to Z is canonical for
plain language; Numbers, units and
precision is canonical for numeric
formatting. Link, do not repeat.
assert-iachecks for restatement. - Do not hand-write a generated section. Tokens, contrast numbers, keyboard
tables, prop tables and the catalogue are produced by
pnpm run generate.
Gotchas
- The H2 check is exact. "Not this" and "What not to do" are not the same heading, and the build says so.
kindis not a category. It selects an outline. A page about health that is really a step-by-step iskind: guideliving understart/, notkind: healthwith the wrong headings.- Status gating applies only to
kind: component. Every other kind renders its full outline at every status. - The templates are outside
content/docs/on purpose. Moving one inside creates a route and a page with placeholder prose in the search index. - The frontmatter schema and
source.config.tsmust agree.content/_templates/frontmatter.schema.jsonis the machine-readable form;source.config.tsis what the build actually enforces.
Related
- Contributing has the routes in and what each has to clear.
- Anatomy of a component page is the component page contract in full.
- Code style has the conventions that apply inside the templates.
- Reading these docs covers the same contracts, explained for a reader rather than a contributor.
Component checklist
The definition of done across design, code, tokens, tests, accessibility, documentation and safety. The items that are actually enforced are marked as such.
Contributing tokens
Adding or changing a token, and the migration obligation it creates. That obligation exists because a CSS custom property is a public API covered by semver.