Conventions
Where a doc lives, what shape a page takes, and the rules this app enforces at build time rather than in review.
The house style is Writing docs, and it applies to whoever is writing, in any app. What follows is the part specific to maintaining this one.
Every doc in the repo lives here
There is no docs/ at the repository root and none inside an app. A README may
introduce a directory in a paragraph; anything longer belongs under
content/docs, with the README linking to it.
Two copies of an instruction means one of them is wrong within a month.
The generated pages are not yours
content/docs/api/{v1,v2}/reference is gitignored and rewritten on every dev,
build and lint. content/docs/api/go-port.md is generated by
make porting-status and parsed by statshub-api-contract — do not
hand-edit its tables, and do not move the file without updating
packages/tests/api-contract/src/cli.ts, which pins the path.
Failures belong at build time, not in review
Two rules here are enforced by code rather than by a reviewer, and both exist
because dev renders the broken version happily:
resolveIconthrows on an unknown icon name. A silently empty icon is a typo nobody notices until a reader sees a gap in the sidebar.scripts/check-links.tsresolves every internal/docslink, in markdown and in JSXhrefs.
If you add a mechanism that can be got wrong invisibly, add its gate in the same change.
One decision, one place
src/lib/source.tsx holds every decision about how content is loaded — the icon
resolver, the OpenAPI badge plugin, the status badges, the remark set. Read it
before changing any of them, and put new ones there rather than beside the
feature that needed them.
src/app/docs/layout.tsx is the same for navigation: which sections exist and
in what order.
Narrow before you serialise
src/lib/openapi-subset.ts cuts the OpenAPI document down to the operations a
page renders before handing it to the client. Without it, each of 298 pages
would ship the whole 500 KB document; with it, about three kilobytes.
The general rule it stands for: a client component gets the slice it renders, not the corpus it was drawn from.