🗂️

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/discontinued is 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.

Content model · docs.steinhoff.group