Documentation authoring
Sources of truth
Author project guides in docs/. Go reference pages are generated from source comments and standard Example... functions; example JSON downloads are copied from service HTTP fixture folders. OpenAPI is generated separately into api/openapi.yaml:
go run ./tools/cli generate openapiThe root Makefile has two documentation commands:
make build-docs # Build the complete Caddy image
make serve-docs # Serve the existing image at http://localhost:8081
make serve-docs DOCS_PORT=8082 # Use a different host portLocal authoring and validation
For local authoring, use Go 1.27 and Node 24. Run this setup from the repository root, then regenerate the reference whenever Go source comments or example fixtures change:
npm ci
mkdir -p bin
GOBIN="$PWD/bin" go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@v1.1.0
GOMARKDOC="$PWD/bin/gomarkdoc" go run ./scripts/docgen/main.goAfter generating the reference, use the npm commands directly:
| Command | Purpose |
|---|---|
npm run docs:dev | Start the Markdown development server under /docs/ |
npm run docs:build | Build static HTML from the current Markdown and generated reference |
npm run docs:preview | Preview a previously built Markdown site |
npm run docs:check | Check built HTML links, anchors, fixtures, and module coverage |
For full validation, regenerate the reference, run npm run docs:build, then npm run docs:check. The checker requires an existing build. CI follows this sequence before building and checking the Caddy image. The Markdown dev/preview server serves the /docs/ site; the complete image also supplies the welcome page, API viewers, and specification.
The root package.json contains only documentation build commands and dependencies. Site configuration lives in api-docs/.vitepress/config.mjs, with docs/ as the Markdown source directory. npm uses the committed lockfile. VitePress is pinned to 1.6.4, with Vite overridden to version 6.4.3; gomarkdoc is pinned to v1.1.0 in the setup above, CI, and Docker. Generated reference/go/, example downloads, HTML, caches, and tool binaries are ignored by Git. Rebuild after changing code or fixtures; the VitePress development server watches Markdown, but does not regenerate Go pages automatically.
Markdown and navigation
Use relative .md links between authored pages so GitHub and VitePress can both follow them. Use /examples/... for downloadable fixture assets; VitePress prefixes /docs/ during the build. Cross-links to Caddy's /scalar, /swagger, and /openapi.yaml remain outside the documentation base.
Guide and ADR navigation is discovered from filenames and H1 titles. Service and package navigation is discovered from directory index.md pages. The Go generator creates its own package navigation. Do not suppress broken links globally; generation, missing snippet imports, and invalid local links must fail the build.
Import actual source rather than copying code that will drift:
<<< ../../pkg/email/example_test.goResolve the relative path from the Markdown file. Existing guide locations remain short links to canonical pages. ADR filenames and statuses are preserved; add a new record and update adr/README.md when making a new decision.
Go comments and examples
Write package-level descriptions and explain exported declarations with Go doc comments. Put examples in example_test.go, name them Example, ExampleType, or ExampleType_Method, and include an Output: comment for deterministic examples that go test verifies. Keep examples independent of external services; never use live patient data or credentials.
The reference includes exported declarations in every workspace package, including internal/. It does not invent use cases, document every private helper, or interpret arbitrary tests as usage examples. Explain workflows and implementation status in service guides, and link to the relevant generated package page. For branch-specific source links, set DOCS_SOURCE_REF locally or use the Docker build argument with the same name; its default is main.