Contributing to the docs¶
The docs are docs-as-code: they live in docs/, build with MkDocs Material, deploy on every push to master via Cloudflare Pages, and CI gates broken refs with mkdocs build --strict.
If you're writing your first docs PR, this page is the convention sheet.
Pick the right artifact type¶
The directory you write into determines what's expected. Don't put a runbook in architecture/ or vice versa.
| Type | Live where | When to use |
|---|---|---|
| Architecture | architecture/ | Living description of how the system works today |
| ADR | adr/ | Why we chose X over Y, frozen at decision time |
| RFC | rfc/ | Proposal for a major feature, debated before build |
| Spec | specs/ | Frozen feature design at build time |
| Plan | plans/ | Implementation plan for multi-session work |
| Runbook | runbooks/ | Operational how-to for repeated procedures |
| Reference | reference/ | API, models, env vars — lookup material |
| Guide | guides/ | Tutorials and walkthroughs (read once) |
| Postmortem | postmortems/ | What went wrong + what changed |
When in doubt, write an ADR. They're the smallest, cheapest, most useful artifact.
File naming¶
| Pattern | Used by |
|---|---|
slug.md |
Architecture, runbooks, reference, guides, principles, contributing |
NNNN-slug.md (4-digit padded) |
ADR, RFC |
YYYY-MM-DD-slug.md |
Specs, plans, postmortems |
index.md |
Section landing page (one per directory) |
_template.md |
Template (excluded from build via exclude_docs in mkdocs.yml) |
Numbers are append-only — never reuse an ADR or RFC number. Dates are ISO (2026-04-26).
Frontmatter¶
Every published page starts with:
---
title: Short, specific title
description: One-line summary (used in nav tooltips and search)
status: active # one of: new | stub | active | frozen | deprecated
tags:
- architecture
- data-model
---
Status values mean:
new— recently added, may still changestub— placeholder, fill before relying onactive— currently maintainedfrozen— historical record, not updated (specs, plans, postmortems are usually frozen at write time)deprecated— kept for reference only
Writing rules¶
- Lead with the answer. First paragraph says what this page is for and what question it answers.
- Tables for structured data, prose for narrative. Don't force a table when prose flows better.
- Concrete over generic. Reference specific files, line numbers, issue numbers. Avoid "this might be useful for various scenarios."
- Link generously. ADR mentions architecture? Link the architecture page. Architecture mentions a decision? Link the ADR. Cross-linking compounds.
- Mermaid by default for diagrams. Renders in MkDocs and on GitHub. drawio only when mermaid can't express what you need.
- Don't paste code dumps. A 200-line code block in a doc dates instantly. Link to GitHub instead, with a permalink (specific commit) if you need the line to be stable.
- Strunk it. Cut "in order to" → "to". Cut "make use of" → "use". Cut filler paragraphs that say nothing.
What needs updating when making a change¶
This is the cross-doc consequence checklist. Walk it for every meaningful change so nothing gets stranded. Tick or write n/a.
| If you changed... | Also update... |
|---|---|
src/ code |
Tests in tests/ mirroring the path |
| Module structure / package boundaries | Architecture → Packages |
| Request/response shape, route paths | Architecture → Build flow or relevant flow page; Reference for the contract |
| Prisma schema | Architecture → Data model, Reference → Prisma models, and an ADR if the change isn't trivial |
| Scraper for an existing retailer | Architecture → Ingest pipeline if behaviour shifted |
| New retailer | docs/reference/retailers.md (when it exists), seed in prisma/seed.ts |
| Compat rule added/changed | Architecture → Build lifecycle (the rules section) |
| Auth, session, security behaviour | New ADR; docs/architecture/threat-model.md (when it exists) |
| New env var | Reference → Env vars, .env.example |
| New domain term | Glossary |
| New visual / brand token | Design system, and a brand voice doc once #42 lands |
| New page or significant page redesign | A spec under docs/specs/, then page implementation issue |
| Decision that closes off other reasonable alternatives | A new ADR |
| Cross-session-worthy fact (e.g., a tool path, a one-off Windows quirk) | ~/claude-os/ (brain repo) or ~/.claude/projects/.../memory/ (per-machine) |
| Issue scope evolved during implementation | The issue body — keep it accurate |
If a row applies and you haven't updated it, the PR isn't done.
Reviewing¶
When you (or future Claude) reviews a docs PR, check:
- Right artifact type for the content
- Frontmatter complete and accurate (especially
status) - Internal links resolve (CI catches broken refs)
- No stale path references (e.g.,
docs/superpowers/paths from before the migration) - If it's an ADR, the alternatives section is filled out
- If it's a runbook, Last verified date is set
- Mermaid diagrams render (preview locally with
mkdocs serve) - No content that should have been an ADR or RFC inlined into architecture
- The "what needs updating" checklist above was applied
Local preview¶
Hot-reloads on every save. http://localhost:8000.
Strict build¶
Before pushing anything that touches docs/:
Fails on broken internal links, missing nav references, unrecognised page targets. CI runs the same check on every PR.
What does NOT belong in docs¶
- Code comments that should stay with the code. "Why this regex" belongs above the regex, not in a doc.
- PR descriptions. Use the PR description for the PR; if the decision matters, write an ADR.
- Personal notes / scratchpads. Use a brain repo (MASTER's
~/claude-os/) or local files. - Secrets. Obviously.
Templates¶
Each directory with templated artifacts has a _template.md. Copy it, rename, fill. Templates are excluded from the build (configured in mkdocs.yml exclude_docs).
Fill in the placeholders, set status: Proposed, push for review.
Templates evolution¶
If you find a template missing a field you needed, add it to the template (in the same PR as your filled-in artifact). Template improvements compound.
Project board status updates from the CLI¶
The project board has a Status field (Todo / In Progress / Done) that the workflow expects to be kept current. Two ways to update it:
- Quick way:
bash scripts/set-issue-status.sh <issue-number> "<status>"— wraps the gh GraphQL plumbing - Manual way: the underlying calls are in
scripts/set-issue-status.sh— read it once to understand what's happening
Status values: Todo, In Progress, Done.
Auto-close + auto-move-to-Done already work via the project's "Item closed" workflow when an issue closes (via Closes #N in a PR or commit). You only need to manually flip status when you start work (Todo → In Progress) or when an issue is paused/blocked.
Memory updates¶
961tech docs are the canonical source of truth. Two supplementary memory layers exist for cross-session continuity:
~/claude-os/(brain repo) — synced across MASTER's machines via git. Use for facts that span all of MASTER's projects (preferences, identity, cross-cutting infra).~/.claude/projects/<project>/memory/— per-machine, per-project, auto-loaded into Claude sessions on this machine. Use for one-off Windows quirks, local-tool paths, transient session reminders.
When you discover something cross-session-worthy that doesn't naturally fit a docs page (e.g., "the gh CLI is at ~/bin/gh.exe because winget is broken on this Windows box"), update the appropriate memory layer rather than inventing a new docs section.