Docs contribution guide
This page is for anyone who edits this docs tree — the whole guide is one step-by-step “add a page” path plus a catalog of the page patterns that recur across the ~750 pages in the corpus. If you prefer to read up on how locales behave instead, see Docs languages and translations; this page covers the page patterns themselves, not localization.Where the page-type patterns live
Pages in this tree fall into a small set of recognizable patterns. Before you open a blank.mdx, walk the current corpus for a sibling page of your
kind and copy its shape — that costs less than inventing a new layout, and
readers learn one shape per class of page.
- Guides (
guides/*.mdx) — how-to pages a tenant follows end to end: onboarding walks, first sends, channel setup, console walkthroughs, and the hub orientation maps (see The orientation page pattern). A guide is the class the reader “does something with.” - Concepts (
concepts/*.mdx) — one-page explanations of a model or a capability: what it is, how its pieces fit, where its limits sit. A concept is the class the reader “understands something with.” - Channels (
channels/*.mdx) and Voice (voice/*.mdx) — per-channel/per-surface anchor pages. - API Reference (
api-reference/*.mdx), SDKs (sdks/*.mdx), Reference (reference/*.mdx), Legal (legal/*.mdx) — the contract-facing and legal surface. - The Getting Started anchor pages (
introduction.mdx,quickstart.mdx,authentication.mdx,docs-languages.mdx, this page) — the pages a first reader of the whole site needs before anything else.
How to add a page
Adding a page is three steps. All three land in the same commit — a page registered indocs.json but without a pin, or a pin without a nav
registration, is the failure mode this guide exists to stop.
1. Write the page with front matter
Every page opens with YAML front matter carrying the two strings the site and the pin both depend on:2. Register the page in docs.json
docs.json at the tree root declares every nav group and page path. Find
the tab your page belongs to (Documentation, Guides, API Reference,
SDKs, Reference), then the group inside the tab, and place the page path
(without the .mdx extension, relative to the tree root) in the group’s
pages array. Register the English path only — never the
locale-prefixed path (tr/...), because the locale prefix is rewritten by
the site (see
Docs languages and translations rule 3) and the variant
wires itself in.
For most writers the group is one of “Getting Started”, “Channels”, “AI
Agents”, “Concepts”, or “Guides” under their tab; pick the group that already
holds your page’s siblings.
3. Write the source-pin test
A source-pin test is a structural check (in a__tests__ dir) that
asserts the page exists, its front matter is intact, its promised sections
are all present, and its docs.json registration reads exactly once. The
pin is what stops a later edit from quietly dropping a section, a tile, or
the nav registration — and it is the only harness that can hold a .mdx,
because an .mdx cannot be imported as a module.
Write the pin as <page-slug>.source-pin.test.mjs in the __tests__
directory adjacent to the page’s own directory (e.g. guides/__tests__ for
a guides page, concepts/__tests__ for a concepts page, top-level
__tests__ for a root page). The harness is the vitest test global when
present, falling back to node:test, so it runs under both drivers:
node --test <your-pin>.test.mjs —
a plain-node invocation of a content pin is sanctioned; the
pnpm/tsc/vitest ban does not apply to content pins the writer can run as
node). A pin you never ran is the single largest cause of merge-gate
failures.
The orientation page pattern
The orientation map exists when a single dashboard hub accumulates enough consoles that the reader’s question is no longer “how do I use this console” but “where do I run this channel / what does each tile answer” — that threshold has been roughly eight consoles on one hub in this docs set, and it is the point where the tree needs one page per hub instead of leaf pages per console. A hub orientation map (the Audience, Messages, and Developer hubs have one) follows a fixed shape:- The one-sentence question that brings the reader in, answered by the whole map (e.g. where do I run a channel?).
- A tile map — one section per console on the hub, each holding the
console’s live route in a code span (
/messages/sms), the one-sentence question that console answers, first-visit skip conditions (what to do when the console has no sender / no registration yet), and a Docs: line of links to the in-depth guides behind that console. - A closing table that links the in-depth pages the map promised, so the reader’s next click off the hub is already open.
docs.json group its hub’s leaf
guides live in, and write a source-pin that asserts every tile route the
map claims. The Messages hub orientation
and its pin guides/__tests__/messages-hub-orientation.source-pin.test.mjs
are the canonical reference — every section heading, every tile route, and
every Docs: link the map promises is asserted there.
The concept model page pattern
A concept page underconcepts/*.mdx answers how does this capability
actually work — what are its pieces, their order, and their limits? in one
page a reader can read once and remember.
The shape that has worked across the corpus:
- A one-paragraph capability statement at the top — the single paragraph that says what the capability does for the tenant, in the tenant’s vocabulary (not the internal subsystem’s).
- A model diagram or an ordered model section — the piece-by-piece walk of how the capability fits together (the audit-ledger model’s “three planes”, the termination model’s travel modes, every lifecycle’s ordered states). Readers remember the model; the rest of the page is there to fill it in.
- Limits and boundaries — what the capability deliberately does NOT do, where the limits sit, which surfaces move it (consoles, API routes, exports).
- Cross-links out — a concept page ends by naming the guide(s) that put the model to work and the hub page that maps it.
concepts/__tests__/audit-ledger-model-nav.source-pin.test.mjs) asserts
every section the page promises.
The guide page pattern
A guide is a tenant-owned how-to: follow it end to end and one real outcome lands (a first send, a channel registered, a guard set, a checklist walked). The working shape acrossguides/*.mdx:
- Who the guide is for and the outcome it produces, in the first paragraph.
- First-visit skip conditions — the state a tenant in which this guide does not apply (“if you only need plain text, SMS covers it; skip this”) and the prerequisite console state (“until a sender is registered the console routes you to the sender-onboarding flow first”). A guide that names its skip conditions saves the reader a dead walkthrough.
- Live console paths — every console route the guide touches appears
as a literal code span (
/messages/whatsapp,/audience/segments), and the guide matches the live route 1:1 (the pin asserts these routes). - Docs links — the in-depth concept page(s) the guide leans on, in a closing “Docs:” line, so the guide never re-teaches the concept.
When to choose each pattern
- If you are mapping a single dashboard hub with more than about eight
consoles, write one orientation page under
guides/, with a tile-map pin. - If the reader’s question is “how does X actually work” (a model, a
lifecycle, a capability with pieces), write a concept page under
concepts/(capability paragraph → model → limits → links out). - If the reader is DOING something end-to-end (a first send, a channel
onboarding, a console walkthrough, a checklist), write a guide
under
guides/with the first-visit skip conditions named. - Every page — register the English path in
docs.jsonin the same commit, run the pin, and never wire a locale-prefixed path into nav.