Skip to main content

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.
When no sibling matches your page’s shape, pick the closest class above and note the new shape in your commit message so the next writer sees it in history.

How to add a page

Adding a page is three steps. All three land in the same commit — a page registered in docs.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:
Titles and descriptions are what the docs search index puts in front of a reader; write them to the reader’s question, not to the internal feature name. Match the voice of the sibling pages in your class (guides are second-person, imperative; concepts are declarative; orientation maps are pivot-style “What it answers” per tile).

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:
Run the pin yourself before committing (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:
  1. The one-sentence question that brings the reader in, answered by the whole map (e.g. where do I run a channel?).
  2. 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.
  3. A closing table that links the in-depth pages the map promised, so the reader’s next click off the hub is already open.
Register the orientation page in the same 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 under concepts/*.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:
  1. 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).
  2. 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.
  3. Limits and boundaries — what the capability deliberately does NOT do, where the limits sit, which surfaces move it (consoles, API routes, exports).
  4. 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.
The audit ledger model is the reference shape: one paragraph of capability, the model in prose order, limits spelled out, three links out. Its pin (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 across guides/*.mdx:
  1. Who the guide is for and the outcome it produces, in the first paragraph.
  2. 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.
  3. 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).
  4. 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.
Every guide page must document tenant-owned controls only — settings you set for your own workspace, the same carve-out the compliance posture page (Compliance posture overview) states; the product has one platform-global guard (the US federal dialing window) and everything else is tenant-configurable. The guide register is second person, imperative voice.

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.json in the same commit, run the pin, and never wire a locale-prefixed path into nav.
A page that follows none of these shapes is the cost the tree pays per pickup — pick the shape that matches, copy its sibling, and the next writer inherits a pattern instead of a one-off.