Content model
The site has three content shapes, and this wiki is a fourth. None of them are a CMS with a rich-text editor — every one is a typed file, on purpose.
Articles
Live in the database once DATABASE_URL is set; content/articles.ts
seeds it. Seeding is tracked per slug, so appending to the seed file does
reach production. Local development has no database, so it silently falls
back to the seed file — anything DB-dependent has to be checked against a
real deployment, not localhost.
Protocol dossiers
Data, not JSX: content/protocol/*.ts, rendered by
components/site/DossierView.tsx. Add one by writing the data file and
registering it in content/protocol/index.ts.
Two rules that only apply here:
- Every claim carries two labels — evidence tier (how good the data is) and source tier (who is saying it, and their incentive). Never merged.
/protocol/discontinuedis append-only. A retracted claim doesn't get silently edited away; the original wording and the reason it was wrong move there instead.
Skills
Listed in content/skills.ts, rendered at /skills.
This wiki
content/docs/pages/*.ts, registered in content/docs/index.ts, rendered
by components/docs/DocsMarkdown.tsx. Same "data file, not a database"
shape as the dossiers, one level simpler: a page is a title, an emoji, and a
markdown string. See Adding a page.
Why files instead of a database, everywhere
Local development has no DATABASE_URL — a session working on this repo on
a laptop can't reach production Postgres. A committed file is the only store
every session, human or agent, can actually read and write. It's also
versioned, diffable, and works offline, which a live CMS is not. BACKLOG.md
uses the same reasoning for the shared to-do list.