Docs conventions¶
How the published documentation site is put together, and how to write a page that fits it.
The site is built from two sources that behave very differently:
| Tree | Origin | Edit it here? |
|---|---|---|
docs-pub/ |
Synced automatically from the METIS source repo | No — changes are overwritten on the next sync. Edit upstream in METIS. |
automation/, README.md, CONTRIBUTING.md |
Written and maintained in this repo | Yes |
site-overlay/ |
Written and maintained in this repo | Yes — this is how you change the site's view of docs-pub/ durably |
How the build works¶
.github/workflows/docs.yml runs three steps:
.github/scripts/assemble_docs.pybuildssite_src/(the mkdocsdocs_dir): copies the published trees in, renames everyREADME.mdtoindex.mdand rewrites links to match, layssite-overlay/on top, normalizes Markdown for Python-Markdown, and injectstags:front matter fromsite-overlay/tags.yml..github/scripts/check_nav_coverage.pyfails the build if any assembled page is missing from the nav, or the nav points at a page that doesn't exist.mkdocs build --strict.
Nothing needs a workflow edit when a page is added — but step 2 means a new page does
need a site-overlay/SUMMARY.md entry.
The nav lives in site-overlay/SUMMARY.md¶
There is no nav: block in mkdocs.yml. mkdocs-literate-nav reads SUMMARY.md — a
nested Markdown list — instead. Two rules:
- The list must be tight (no blank lines between items). A blank line makes
Python-Markdown wrap each item in
<p>, and literate-nav rejects that. - Order is meaningful. It sets both the sidebar order and the prev/next footer links. Order by the reader's path through the material, not alphabetically — the IRIS job pages are ordered by pipeline position, which is the order an operator meets them.
A section whose title line carries a link uses that page as the section's landing page
(Material's navigation.indexes), so "Job reference" opens the IRIS job index rather than
merely expanding.
Adding a page¶
- Upstream in METIS, under
docs-pub/: add the file there, then add one line tosite-overlay/SUMMARY.mdhere, and a row to the relevant table insite-overlay/docs-pub/index.md. Until you do, CI fails — deliberately: an unreachable published page is worse than a red build. Two pages (api/outreach-PLAYBOOK.md,metis_apps/gathering/experience-images-howto.md) sat live and unlinked before this check existed. - In this repo, under
automation/: anyREADME.mdunderautomation/is picked up automatically; still add theSUMMARY.mdline.
Tags¶
site-overlay/tags.yml maps page paths to tags. Tags live there rather than in the pages
because front matter added to docs-pub/ would be lost on the next sync. The vocabulary
is deliberately small (linkedin, publishing, permissions, api, configuration) and
enforced by tags_allowed in mkdocs.yml — a typo fails the build instead of quietly
creating a one-page tag. A tag that lands on half the site sorts nothing; if a new tag
wouldn't group at least three pages that are far apart in the nav, it isn't earning its
place.
Writing a page¶
The IRIS job pages are the model to copy. Every one of them opens with the same key-value table and then follows the same heading spine — so a reader who has read one can navigate all nineteen without re-orienting. Aim for that property per document type.
Every page¶
- An H1 that names the thing, not the section it sits in.
- A lede of one or two sentences that says what the page covers and who it is for. A page must stand on its own: most readers arrive from search, not from the index, so "who should read this" belongs on the page rather than only in the index table.
- No hand-numbered headings. Don't write
## 2.2.4 Job Steps. The sidebar numbers itself, and hand numbering has to be rewritten every time a page is inserted. - Links to sibling pages by relative
.mdpath (youtube-uploader.md,../using-iris.md), so they work both on GitHub and on the site.
Reference pages (one page per unit of a repeating thing)¶
Follow the IRIS job pattern exactly:
- A key-value table at the top: what identifies this thing (label, slug, source file, class, dependencies).
- Then the fixed spine: Purpose → Pipeline position → Data flow → Requirements → Behavior details → Testing this step → Related runbooks.
- The set of them gets an index page that is a table, not prose: one row per page,
with the columns a reader scans by.
docs-pub/metis_apps/coherence/iris/jobs/README.mduses # / Job / Slug / Depends on / Purpose, and fits nineteen pages on one screen. - The index says what has no page of its own and what is legacy. Navigation honesty: a reader who can't find a page should learn why from the index.
- Where the structure isn't linear, draw it — the ASCII branch diagram in the IRIS job index conveys the two-branch shape faster than any amount of prose.
Guides and how-tos¶
- Lead with the outcome, then the click-path in order.
- Prerequisites go in an
!!! noteadmonition before step 1, not scattered inline. - If the guide is for a specific audience (participants, administrators), say so in the
lede — see
iris/participant-approval.md.
Placeholder pages¶
A page whose guide isn't written yet must say so in its own body, in an admonition:
!!! warning "Placeholder"
The usage guide for this app has not been written yet. This page exists so the
section has a home; it will be filled in.
Don't leave the fact that a page is a stub visible only from the index — readers arriving
from search deserve to know within one screen. metis_apps/audax/quests-and-missions.md,
metis_apps/outreach/linkedin-outreach.md and web/invite/signup.md are the current
stubs; they still need this treatment upstream in METIS.
Building locally¶
python3 -m venv .venv
.venv/bin/pip install mkdocs-material mkdocs-literate-nav
python3 .github/scripts/assemble_docs.py
python3 .github/scripts/check_nav_coverage.py
.venv/bin/mkdocs serve
site_src/ and site/ are both generated and both git-ignored — never edit them.