Start here
ADR-0005: Docs for agents
Status: accepted · 2026-10-18
Context
An app built from botgumi has many documents: the PRD, the brand and design work (system, lo-fi, hi-fi, binding maps), the backend, iOS and Android specs, the OpenAPI contract, the dashboard, the landing page, the ADRs, the tracking plan, the store and go-live checklists. Agents read them on every task; people read them at every gate.
The first app built this way kept its docs as Markdown next to the code, plus one-page spec sites built from them
by a script with a --check flag that CI ran. That worked where it was used: the pages could not drift from the
docs. Where nothing checked, links and pages went stale. The docs were also only readable by cloning the repo or
opening a hand-made page; an agent outside the repo had no index to start from.
Cloudflare publishes its docs for agents in a fixed shape (developers.cloudflare.com/docs-for-agents): a site index
at /llms.txt grouped by product, each product's /{product}/llms.txt and /{product}/llms-full.txt, a site-wide
/llms-full.txt, and every page as Markdown at {page}/index.md or for Accept: text/markdown. It follows the
llms.txt convention and needs nothing but static files.
Decision
D1. The docs live in the app repo as Markdown, next to the code. docs/ holds the cross-track pages (PRD,
tracking plan, API, ADRs, checklists); each track keeps its own pages in its folder (design/, backend/, ios/,
android/, landing/, dashboard/). No second copy anywhere.
D2. One manifest lists every page by module. docs/manifest.json: the site title and summary, then modules,
each with a slug, a title, a one-line description, the track that owns it, its pages (slug, source, title,
optional description and section) and files served as they are. The template's modules:
| Module | Pages | Owner |
|---|---|---|
overview |
the repo README, how the docs work | docs |
product |
PRD, tracking plan | docs |
design |
brand, design system, lo-fi, hi-fi screens and their binding maps, screenshot direction | design |
api |
the API page; openapi.yaml, linked as it is |
docs |
backend, ios, android, landing, dashboard |
the track's README and specs; the store checklists under ios and android |
that track |
decisions |
the ADRs | docs |
go-live |
the go-live checklist, the secrets inventory | docs |
D3. One generator, @botgumi/docs. build(manifest, readFile) returns the files; it is pure, so the CLI, the
tests, the dev server and botgumi.com run the same code. It writes:
| Path | What |
|---|---|
/llms.txt |
the site index: every module with its description and links to its llms.txt and llms-full.txt, then each of its pages and files |
/llms-full.txt |
every page in one file |
/{module}/llms.txt |
the module's index, pages grouped by section, then its files |
/{module}/llms-full.txt |
the module's pages in one file |
/{module}/{page}/index.md |
the page: front matter (title, description, source), a line linking its module and the site index, the Markdown |
/{module}/{name} |
a file as it is (the OpenAPI contract at /api/openapi.yaml) |
/{module}/{page}/, /, /404.html |
a small HTML site of the same pages |
Links between pages are rewritten to the published pages; a relative link to a file outside the docs becomes its text and a build warning. Raw HTML in a page shows as text in the HTML site.
D4. The output is committed and checked. pnpm docs:build writes docs/public/. pnpm docs:check builds in
memory and fails when a source is missing or docs/public/ differs from the build in any file. CI runs it on every
PR, so a PR that changes a doc rebuilds the output in the same PR. Agents in the repo read docs/public/llms.txt
and the index.md files directly.
D5. The same build serves locally and hosted. pnpm docs:dev serves the docs on localhost, rebuilt on every
request. Hosted, docs/public/ is the static assets of a Cloudflare Worker on docs.<app domain> (the core stack);
the Worker runs first to answer Accept: text/markdown with a page's index.md and to set content types
(text/markdown for .md, text/plain for .txt, application/yaml for the contract). The dev server and the
Worker share one request-to-file function.
D6. Private by default. A PRD and a tracking plan are not public. The docs hostname sits behind Cloudflare
Access (one application, allowing the owner), and the Worker's workers.dev and preview URLs are off so Access
cannot be bypassed. Making the docs public is the owner's choice: remove the Access application.
D7. Creation. botgumi new writes docs/manifest.json and the first pages from the templates (PRD review,
tracking plan, ADR-001, the API page, the docs README, the design README), copies botgumi's checklists, drops the
modules of tracks the app does not have, and runs docs:build, so the first commit passes docs:check.
D8. Updates. Each worker's "Done" includes its module's pages updated when the PR changes behaviour, a
contract or a design, and docs:build run. A new page is a Markdown file plus its manifest line. Review rule
"docs updated for changed behaviour" is blocking. The upgrade bot's PR refreshes the copied checklists and
@botgumi/docs, then rebuilds; the output diff is part of that PR.
D9. botgumi.com serves its own docs the same way. The site builds its /llms.txt, /llms-full.txt,
/docs/llms.txt, /docs/llms-full.txt and /docs/{slug}/index.md with @botgumi/docs from its sidebar manifest
and the Markdown the HTML pages render. Its docs pages also answer Accept: text/markdown.
Consequences
- An agent outside the repo needs one URL (
/llms.txt) and, for a private app, an Access service token. - Every doc change carries a generated diff in
docs/public/. Reviewers skip it;docs:checkproves it matches. - Docs content stays English, like botgumi.com's docs (ADR-0001, decision 7 covers UI strings). The generated HTML site has no prose of its own: titles come from the manifest, the rest are file names.
docs/public/is rebuilt whole, so nothing hand-made may live in it.- Follow-up: a CI workflow in the app template that runs
docs:checkwith the other tracks' checks; an Access service token for agents that read hosted docs; the design stage pages (ADR-0004) join thedesignmodule.