Skip to content

Docs Authoring Conventions

Use these patterns when writing or updating any page under docs/. They ensure consistent rendering with the branded VitePress theme.

Callouts / Admonitions

VitePress natively renders ::: fenced blocks — no plugin required. Use them instead of blockquote-style callouts (> **Note:** …).

Tip

Use for a helpful aside or a shortcut the reader will appreciate.

Source:

md
::: tip
Run `npm run storybook` to preview every component in isolation before opening a PR.
:::

Rendered:

TIP

Run npm run storybook to preview every component in isolation before opening a PR.


Info

Use for neutral context — something the reader should know but that doesn't require action.

Source:

md
::: info
Docker Compose maps the frontend to port 8282. Local Vite dev (`npm run dev`) uses port 5173.
:::

Rendered:

INFO

Docker Compose maps the frontend to port 8282. Local Vite dev (npm run dev) uses port 5173.


Warning

Use for a non-blocking caution — something that can go wrong if the reader doesn't pay attention.

Source:

md
::: warning
The header is `SessionToken` (PascalCase), not `Authorization: Bearer`. Wrong header = silent auth failure.
:::

Rendered:

WARNING

The header is SessionToken (PascalCase), not Authorization: Bearer. Wrong header = silent auth failure.


Danger

Use for a destructive or irreversible action — data loss, breaking changes, or security-sensitive steps.

Source:

md
::: danger
PITR replaces the instance's data. Confirm the target timestamp carefully. Do this on staging first if the cause is unclear.
:::

Rendered:

DANGER

PITR replaces the instance's data. Confirm the target timestamp carefully. Do this on staging first if the cause is unclear.


Details (collapsible)

Use for supplementary information that most readers can skip — long rationale, historical context, or edge-case details.

Source:

md
::: details Why we use `public_id` instead of database IDs
Integer primary keys leak record counts and insertion order to clients. `public_id` is a URL-safe base64 token auto-generated by `PublicRecord` — it's opaque, short, and safe to expose in URLs and API responses.
:::

Rendered:

Why we use public_id instead of database IDs

Integer primary keys leak record counts and insertion order to clients. public_id is a URL-safe base64 token auto-generated by PublicRecord — it's opaque, short, and safe to expose in URLs and API responses.


Tabbed Code Groups

Use ::: code-group to show equivalent commands or configs side-by-side.

Source:

md
::: code-group

```bash [npm]
cd ionic_frontend
npm install
npm run dev
```

```bash [Docker]
docker-compose up --build
# Frontend available at http://localhost:8282
```

```ruby [Rails console]
# Rails API only
cd rails_api
bin/rails server
```

:::

Rendered:

bash
cd ionic_frontend
npm install
npm run dev
bash
docker-compose up --build
# Frontend available at http://localhost:8282
ruby
# Rails API only
cd rails_api
bin/rails server

When to Use Which

BlockUse when
::: tipHelpful shortcut or best-practice the reader will thank you for
::: infoNeutral context — good to know, no action required
::: warningNon-blocking caution — something can go wrong without care
::: dangerDestructive or irreversible — data loss, credential exposure, breaking change
::: detailsCollapsible extra — rationale, history, or edge cases most readers can skip

Do NOT use raw blockquote callouts (> **Note:** …) for new content — convert existing ones to the matching native block when you edit a page.


Cross-Linking PRDs and Feature Docs

When a PRD ships and is archived to docs/product/completed/, it and its corresponding docs/features/*.md page must link to each other. This keeps product rationale discoverable from the shipped doc, and the shipped implementation discoverable from the design history. See docs/features/meet-coach.md / docs/product/completed/meet-coach-prd.md for a reference pair (established in OBJ-1467).

Feature doc → PRD. Add a bullet to the page's existing "Related" list (usually near the top):

md
- [<PRD Title>](../product/completed/<prd-slug>.md) — original product rationale and design exploration

PRD → feature doc. Add a bullet to the PRD's "Related" list, or a ## Related Documentation section near the bottom (before the **Last updated:** line) if it doesn't have one:

md
- [<Feature Title>](../../features/<feature-slug>.md) — feature doc for the shipped implementation

Checklist when archiving a PRD to completed/:

  • [ ] Check whether a docs/features/*.md page exists for the shipped feature — not every PRD has one, skip if so.
  • [ ] Add the backward link (feature doc → PRD) using the phrasing above.
  • [ ] Add the forward link (PRD → feature doc) using the phrasing above.
  • [ ] Keep the phrasing consistent — it signals link intent (rationale vs. implementation), not just "see also."

Page Footers

Every page under docs/ ends with exactly one **Last updated:** line — one entry, one line. This is non-optional.

md
**Last updated:** YYYY-MM-DD (OBJ-NNNN: <one clause describing the change>)

This file's own footer, at the very bottom of this page, is a live example of the correct shape.

Never chain entries. Do not prepend Previous entry:, Same day:, Prior entry:, Earlier entry:, or any similar construction onto an existing footer to preserve older changes. When you touch a page, replace the whole footer line with a single new entry describing the most recent change. Change history belongs in git log (git log --follow <path>), not in the footer — every prior entry already cites its own OBJ/PR number there and is fully recoverable.

A chained footer isn't just noisy: because it's one physical line, any two concurrent PRs touching the same doc conflict on it with certainty, and because the line carries prose from multiple unrelated tickets, resolving the conflict requires synthesizing narrative rather than a mechanical pick. See the gotcha write-up for the incident this rule was written to prevent.

Last updated: 2026-08-14 (OBJ-2562: codified the one-entry footer rule)

Loading…