The problem it exists for
There are 146 active projects in the estate, and every one of them has docs that can go stale without anyone touching them. The case that made it obvious: three of krites’ pages told readers to run a command that had stopped working when it gained subcommands. The merge request that fixed those pages ran only the security jobs and the docs build, because a docs-only change skips the code gates, so nothing would have caught the next one either (spec 0068).
The readers changed too. By September the docs sites were 71% of the estate’s search impressions, AI crawlers were fetching hundreds of pages a week, and assistants were fetching keryx’s Instagram how-to on users’ behalf when Google sent it nobody (spec 0089). So the docs have to be right, findable, and readable by a machine that will quote them.
How it works
One site per project, built by one component
73 public projects have their own docs site, at <name>.phpboyscout.uk or <module>.go.phpboyscout.uk, built with Zensical by cicd’s zensical-pages component. Each one builds on every docs change and deploys from main. The 41 adapter modules (each config backend, chat provider and forge adapter) deliberately have no site of their own and are documented on their family’s. The toolchain lives in a build image rather than each repository, after hand-maintained lock files left 18 update merge requests stuck at once (spec 0039).
Written for the machines too
Because every site is built by the same component, an improvement lands everywhere without a change in any repository. The component writes an llms.txt map of each site for AI agents (spec 0089), adds structured data naming the site, the software and its author on every page (spec 0091), honours the exclusions Zensical ignores, so scaffold pages stop being indexed (spec 0090), and fills in the “edit this page” link, which had pointed every site at a branch that doesn’t exist (spec 0092).
The same shape everywhere
Every site follows Diátaxis: tutorials to learn from, how-to guides for a task, reference to look things up, and explanation for the why. 62 of the 73 sites have all four. How-to and reference pages open with the answer, in under a hundred words before the first example. Tutorials live in each project’s own docs, and when the blog runs one, it’s a copy that points back to the docs as the original. A tool built on go-tool-base gets the layout generated for it. The rule itself is a skill every agent session reads (diataxis-docs).
Specs don’t live in the docs. They’re decision records, so they go on each project’s wiki, and the docs link to them. The test for what moves is whether a page would need updating when the code changes.
Checked against the code
docs-verify runs a project’s own docs check on every merge request, with no filter on which files changed, because the code change that breaks a page doesn’t touch the page. The component supplies the guarantee and the project supplies the check. docscheck is one such check: it reads the command examples in a tool’s docs and fails when one names a subcommand that doesn’t exist. It’s narrow on purpose. The obvious broader rule “found 15 problems on a corpus whose real defect count was 3.” Rust projects get the same from cargo doc treating warnings as errors, on all 12.
Beyond the gates, two agents in the estate’s plugin marketplace check docs on demand: one audits every signature, flag, config key and snippet against the source and fixes nothing, and the other writes to the Diátaxis shape and finishes with a merge request.
Answerable by the bot
phpbotscout answers support questions from these sites, with citations, so it doubles as a test of whether they answer anything. In August it reviewed the docs of 48 projects. Across 829 pages it found reference was the weakest part and mattered most, that the “why” had been left in specs the bot can’t read, that limitations weren’t written down, and that sections didn’t stand alone when retrieved one heading at a time. Every one of those reviews was closed the next day. keryx gained a reference section, a limitations page and its first tutorial. config gained six reference pages documenting all 21 of its errors.
Decisions and what they cost
- One map writer. The alternative was “66 merge requests to add a file every site derives identically”, and a hand-written map drifts (spec 0089). What it cost: the generator lives inside the component’s template, with a self-test that its copy matches the canonical one. A full-text dump for language models was turned down as “a training-data gift with no evidence anyone fetches it”.
- Builds follow docs changes. A site only rebuilds when its own docs change. What it cost: a component improvement reaches a site only on that site’s next docs change. 21 module sites still have neither the map nor the structured data.
- A narrow checker. What it cost: docscheck checks command paths only, so a renamed flag or a wrong argument still gets through.
- Tutorials moved into the docs. What it cost: every blog tutorial was copied back and rewritten in the tutorial register.
Proof in use
- 73 docs sites, all live, with 1,652 pages between them. The largest are go-tool-base’s (268), keryx’s (128), and config’s and cicd’s (72 each).
- 61 sites have at least one tutorial, and 38 have a limitations page.
- 52 sites already carry the AI map, and 50 the structured data.
- 48 bot-led reviews, then 72 follow-up passes comparing each README and its docs with each other and with the code, 44 of them finished.
Borrow it when, and when not to
Borrow it if you run more than a handful of projects and want their docs consistent without editing each one: put the build in one shared component and every site gets each improvement. Diátaxis and an answer-first rule carry over to any docs tool.
Only krites has a docs check wired into docs-verify so far, and docscheck checks command paths only. No site has automatic link checking: links are checked by the auditing agent, and after a restructure. Zensical has no redirects of its own, so a renamed page needs a redirects file. Two sites, cicd’s and phpbotscout’s, name their GitLab repository as their own address, so search engines and the map point there rather than at the site. go.phpboyscout.uk is hand-written and has no map.
Where it’s going
Rebuilding the 21 sites that predate the map and structured data (cicd#75), pointing cicd’s and phpbotscout’s sites at their own addresses (cicd#76, phpbotscout#22), and the 28 follow-up passes still open, such as keryx#25 and config#7.
Last reviewed .