Skip to content

Writing documentation

Voice's documentation is one tree of plain Markdown under docs/, and every way of reading it is a rendering of that tree: the site at https://docs.makethemlisten.uk/, llms.txt, llms-full.txt, a Markdown copy of each page, docs-index.json, and the agent skill in the marketplace plugin. The tool that renders and checks it is ankka's, taken as a dependency, and the rules are ankka's too; the page Writing documentation in ankka's documentation states every rule with its reason. This page says what is particular to this repository.

The build

uv run --project tools/docs docs check    # every rule; exits 1 on a problem
uv run --project tools/docs docs sync     # refresh the rendered skill
uv run --project tools/docs docs build    # check, build the site, write the machine renderings
uv run --project tools/docs docs serve    # the site with live reload, while writing

just docs, just docs-sync and just docs-serve are the same commands. The site lands in target/docs-site. The tool comes from ankka's repository, named in tools/docs/pyproject.toml, and what it needs to know about this repository is extra.docs in mkdocs.yml: the frontmatter vocabulary, where the skill is rendered, and which files outside docs/ link to the site.

The site is published to GitHub Pages from main by .github/workflows/docs.yml, which also runs the build as a check on every pull request that touches the documentation. The custom domain is set in the repository's Pages settings with a DNS CNAME to the Pages host, and Pages is enabled with "GitHub Actions" as its source, once.

Where a page goes

Kind Directory The reader wants to
tutorial get-started/ be walked from nothing to something working
concept concepts/ understand how something works and why
guide build/, deploy/ get one task done
reference reference/ look one fact up
contributing contributing/ change Voice itself

The build/ directory is the "Use" section of the site: one page per stage of the loop, each with the routes it uses, for a participant, a reviewer, a representative or an operator, and for anyone writing a client or another interface. A new page is added to the nav in mkdocs.yml and, unless it is a contributing page, to the skill's pages: list, or the check fails.

Frontmatter

Every page starts with title, description and kind. One optional key is this repository's: audiences, any of reader, participant, reviewer, representative and operator, for a page written for one or more of them. related lists the pages a reader most often needs next.

The words

A page uses the words of the glossary in the one sense it gives them: a participant is a citizen as Voice knows them; a concern is a statement and an issue is the public topic; a contribution is approved by its participant and published by a reviewer; a priority is an opinion. The glossary page is written from GLOSSARY.md at the root of the repository, which the living features are checked against, so a term changes there first; the page is regenerated by hand from it, one bold term and its sentence per entry, with each "Avoid" line rendered as the words the term is not called.

Voice, the product, is capitalised, as the glossary has it; voice in backticks is the service.

The example

Every page that needs an example uses the seed pack's issue, "Rural school bus withdrawal": Route 14 between Kingsway and Northfield, the council's count of eleven pupils against the parents' count of twenty-three, the unanswered question about the ring road works, and the two options. Replies shown are the service's own, from a run against the pack, shortened where the page says so. Identifiers in them are from that run and differ on another machine.

What a page must not say

A page tells no history: no feature or task numbers, no requirement identifiers, no "previously". It names no positional neighbour, since a reader may arrive at any page from a search. Every code fence has a language, text for output. A link to another page is relative and ends in .md; a link outside docs/ is a GitHub URL. The check refuses each of these.

The skill

One skill, voice, is curated in tools/docs/skill/voice/SKILL.md and rendered into marketplace/plugins/voice/skills/, which is committed and checked. Its body holds the rules an agent must hold to use Voice's routes or write against them; the pages themselves are generated into it from docs/. A version tag publishes the plugin to the family's marketplace; Releasing.