---
title: "Docs for agents"
source: "docs/decisions/ADR-0005-docs-for-agents.md"
---

> Part of [botgumi docs](https://www.botgumi.com/docs/llms.txt). Every page: [llms.txt](https://www.botgumi.com/llms.txt).

# 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:check` proves 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:check` with the other tracks' checks; an Access
  service token for agents that read hosted docs; the design stage pages (ADR-0004) join the `design` module.
