How this handbook stays current
Documentation does not go stale because someone is careless, but because the same statement lives in two places and only one is changed. This handbook therefore keeps one source per statement and lets guards check what can be checked. What cannot be checked is said here explicitly.
One source per statement
| Statement | Source | How it gets onto the pages |
|---|---|---|
| Binding behaviour | docs/spec/ |
linked, never copied; when in doubt the spec wins |
| Code a page shows | the file in the repository that is also built (examples/first-app, the apps’ registers) |
Source.astro embeds it verbatim |
| What a surface does | the story in Storybook, with the real toolkit components | Story.astro embeds it; the id is checked against the built index |
| All hooks | the documentation comment above every exported hook | pnpm docs:hooks generates all-hooks.json, Storybook and the reference render it |
| Packages, spec list, agent entry points | the packages’ package.json, docs/spec/README.md, all-hooks.json, examples/first-app |
pnpm docs:agents generates llms.txt and the app template’s code block |
| Terms | the family’s term register (SKOS, docs/reference/rls.skos.jsonld) |
glossary page, in progress |
| State of the build | git commit, versions of app and toolkit | prepare.mjs writes build-info.json, the footer shows it |
The guards
Every page names in its frontmatter the files it draws its statements from (sources) and the stories it embeds (stories). pnpm check:site fails when a source file is missing, a story id is not in the built Storybook index, an embedded story is not declared, a link between pages leads nowhere or a translation is stale. After the build it also checks every local link of the finished site. pnpm test:site checks that the guard recognises deliberately broken pages.
pnpm check:hooks and pnpm check:agents check the same for the generated parts: an exported hook without a complete block, a story id that does not exist, a package without description, or a generated file that no longer matches the repository turns CI red. All of them run in .github/workflows/tests.yml; the overview is under Work with agents → The checks.
What moves along automatically, and what does not
When a component changes, its story changes, and with it the picture on the page. When the example changes, the shown code changes. When a hook comment changes, the reference changes. When a source file is renamed or deleted, the guard fails.
Not automatic: whether a sentence is still true. When a behaviour a page describes changes, no guard reports it; that is the documentation impact every PR names (Working on the stack together). Especially for permissions, data storage and deployment a person checks.
Two entrances, the same pages
The site reads docs/handbook/<language>/; the pages live in the repository so that they are read in the PR like the spec. Before every build, prepare.mjs writes the same pages as Markdown to /markdown/<language>/<page>.md (embedded code written out, stories as links) and appends them to /llms.txt. So agents read what people read, not a summary.
German first, English after
German is the root (/handbuch/…), every other language a prefix (/en/handbuch/…). A translation names its German source in the frontmatter (translationOf) and its hash at the time of translation (sourceHash). When the German page changes, the hash no longer matches and the guard reports the translation as due for review. A page that exists only in German is linked by the English index as the German page; there are no placeholders.
Working locally
pnpm dev:site # preview with live reload, stories from the running Storybook (6006)pnpm build:storybook && pnpm build:site && pnpm check:site && pnpm test:sitepnpm preview:site # the built site, as it is deployedThe site is deployed together with Storybook and app from deploy-prototypes.yml; the footer of every page names commit and versions of the state you are looking at.