The docs site is built through a three-stage pipeline: discover → validate →
build. The same pipeline runs locally (via Compose) and in CI (via Forgejo
Actions with Buildah), using identical tooling packaged in the docs-builder
image.
Pipeline stages
1. Discover and mount (hugo-mounts-helper)
hugo-mounts-helper scans sibling repos at ../* for docs/ directories and
generates build/mounts.toml — a Hugo module mounts configuration that overlays
external content into the site’s virtual content/ tree.
Config: config/hugo-mounts-helper.yaml
Fixed mounts map local sources into Hugo’s mount namespace:
| Source | Target | Purpose |
|---|---|---|
site/content | content | Hand-written content from this repo |
build/content | content | Generated _index.md files for category grouping |
site/layouts | layouts | Template overrides and shortcodes |
site/assets | assets | CSS, JS, images |
Discovered mounts are added dynamically per sibling repo. Standard Diátaxis
categories (explanation/, guides/, reference/, research/, tutorials/)
are mapped directly. The decisions/ category is special: ADRs are grouped by
their category frontmatter field (e.g., bootstrap/docs/decisions →
content/decisions/architecture), and _index.md files are generated under
build/content/decisions/ for each group.
2. Validate (smadr-validator)
smadr-validator finds all ADR files across discovered sources and validates
them against:
- A JSON schema (
internal/smadrvalidator/schemas/dataverket-policy.schema.json) - Organizational rules: allowed projects, categories, statuses, required sections, filename patterns, duplicate detection
Config: config/smadr-validator.yaml
In the build entrypoint (compose/docs-builder/docs-builder.sh), the validator runs in
--mode advisory — warnings are printed but don’t fail the build.
CI adds a separate strict validation step before the full site build so blocking ADR issues fail the pipeline before Hugo runs.
3. Build (hugo)
Hugo builds the static site using a merged config:
config/hugo.toml— base config (theme, Kroki endpoint, output formats)config/hugo.ci.toml— CI overlay (adjusts Kroki endpoint for service networking)build/mounts.toml— generated module mounts from step 1
Output goes to build/public/. The Relearn theme and Kroki Hugo module are
vendored under _vendor/.
Kroki runs as a sidecar service (Compose service kroki + mermaid) and
renders diagram code blocks inline during the Hugo build.
Entrypoint
All three stages are sequenced by compose/docs-builder/docs-builder.sh, which is the
default CMD of the docs-builder image:
hugo-mounts-helper → smadr-validator → hugo --minifyImages
| Image | Base | Contents |
|---|---|---|
docs-builder | hugomods/hugo:base-0.160.0 | Hugo + 3 Go tools, docs-builder entrypoint |
The builder image is a multi-stage build: a Go stage compiles the three CLI tools, then copies them into the Hugo base image. Hugo modules are pre-vendored so the final image doesn’t need Go.
Local development
task build # full pipeline inside docs-builder container
task dev # dev server with livereload (watches for changes)
task start # build once and serve in background via CaddyThe dev task starts dev-reload-notifier (an SSE server) alongside Caddy
with Caddyfile.dev, then watches source files and rebuilds automatically.
After each rebuild it fires a livereload trigger so the browser refreshes.
CI pipeline
Defined in .forgejo/workflows/docs-site-pipeline.yaml:
- verify-go — runs
go test,go vet, andgo buildacrosscmd/andinternal/ - build-toolchain — builds and pushes the
docs-builderimage using Buildah - build — discovers sibling org repos (those with a
.docs.yamlmarker), clones them, runs strict ADR validation, then runs the full build inside the toolchain image
Separate workflows handle toolchain image publishing
(docs-builder-image.yaml) and container security scanning
(docs-container-scan.yaml).
Deployment
| Method | Command | Description |
|---|---|---|
| Compose | task start | Build once, Caddy serves build/public/ |
| Compose (dev) | task dev | Live-reload mode with Caddyfile.dev |
| Codeberg Pages | task deploy:codeberg | Pushes build/public/ to the pages repo over SSH |
| Tilt | task tilt:up | Watches sources, live_update syncs into Caddy pod |