The Docs Pipeline¶
This handbook is part of the flake. The same repository that builds the editor
also serves the documentation locally, builds it into a static site, and
renders it to a Kartoza-branded PDF — all through nix run .#… apps that
carry their own toolchain, so you never need a nested nix develop.
The apps¶
| Command | What it does |
|---|---|
nix run .#handbook |
Serves the site locally with live reload at http://localhost:8001. |
nix run .#handbook-build |
Builds the static site into ./site with --strict. |
nix run .#handbook-pdf -- out.pdf |
Renders the whole handbook to a Kartoza-branded PDF. |
nix run .#handbook-keymaps |
Regenerates the keymap tables + keyboard SVGs from the live keymaps. |
nix run .#handbook-addons |
Regenerates the Overview add-ons table + diagram from lib/addons.json. |
Run them from the repository root — they operate on mkdocs.yml and docs/
in the current directory.
The last two are generators: they write Markdown and SVGs into docs/ that
are checked into the repo. CI runs both before building the site and PDF, so the
published docs are always regenerated from source. See
Generated pages below.
Serve locally¶
This runs mkdocs serve -a localhost:8001. Open
http://localhost:8001 and edit files under docs/;
the browser reloads automatically. The MkDocs and Material stack is provided
by the flake's docsPython (a python3.withPackages bundling mkdocs,
mkdocs-material, the Material extensions, glightbox and the git-revision-date
plugin), placed directly on PATH.
Build the site¶
This runs mkdocs build --strict and writes the site to ./site. The
--strict flag turns warnings — broken internal links, pages missing from the
nav, bad references — into hard errors, so this is the command that proves the
docs are publishable.
Run the strict build before you push docs
A page you added but forgot to list in the mkdocs.yml nav, or a link
with a typo, passes a casual serve but fails --strict. CI runs the
strict build; run it locally first.
Render the PDF¶
This assembles a single Kartoza-branded PDF via pandoc + texlive. The
app puts pandoc, a trimmed pdfLatex combine, librsvg and shell utilities
on PATH, exports the docs and PDF-template directories, and executes
lib/docs-pdf.sh. The pdfLatex combine is built from scheme-medium plus
explicit extras (including the Kartoza brand font Lato and the
Inconsolata code font) to keep the closure lean rather than pulling in
scheme-full.
Generated pages¶
Two parts of the handbook are generated from source, never hand-edited, so they can never drift from the actual configuration:
| Generator | Source of truth | Writes |
|---|---|---|
nix run .#handbook-keymaps |
timvim's live keymaps (the built Neovim, queried headless) | docs/reference/keymap.md, docs/reference/which-key.md, docs/reference/completion.md and the keyboard/leader/completion SVGs under docs/assets/diagrams/ |
nix run .#handbook-addons |
lib/addons.json |
docs/overview/addons.md and docs/assets/diagrams/addons.svg |
The add-ons generator (lib/gen-addons-docs.py) also drift-checks the
manifest against the live config tree: every .nix file under
config/{plugins,ui,utility,assistant} (bar default.nix) must be referenced
by some add-on's configs list, and every referenced file must exist. Add or
remove a plugin without updating lib/addons.json and the generator exits
non-zero — so the Overview is guaranteed to match what
actually ships.
To document a new add-on: add an entry to lib/addons.json (name, category,
one-line purpose, upstream url and the configs it is wired from), then run
nix run .#handbook-addons. Categories are defined at the top of the same file.
Where the Kartoza theming lives¶
The brand presentation is factored out of mkdocs.yml so it can be reused:
| Location | Contents |
|---|---|
docs/stylesheets/kartoza-tokens.css |
The brand tokens — the Kartoza palette and type variables. |
docs/stylesheets/extra.css |
The adapter that maps those tokens onto Material for MkDocs (custom primary/accent, eyebrows, CTA styling, grid cards). |
docs/assets/brand/ |
Brand imagery: logos, favicon, cover banner, motif and slant dividers. |
docs/pdf/ |
The LaTeX templates for the PDF: preamble.tex (fonts, colours, headers) and cover.tex (the branded cover page). |
Both stylesheets are wired in through extra_css in mkdocs.yml; the mermaid
runtime is loaded via extra_javascript.
lib/docs-pdf.sh¶
The PDF is not produced by a MkDocs plugin — it is assembled by
lib/docs-pdf.sh, invoked by the handbook-pdf app. Understanding it matters
because it has one maintenance obligation that is easy to miss.
What the script does:
- Orders the chapters. It holds an explicit
PAGESarray listing every markdown file in reading order, then concatenates them with\newpagebetween chapters. - Transforms each page from MkDocs-flavoured Markdown into something
pandoc/pdflatex can render: it strips YAML front-matter, replaces each
mermaid fenced block with a pointer to the online handbook, flattens
admonitions to bold labels (dedenting their 4-space bodies), drops
grid-card and raw-HTML wrappers and
++key++markup, and transliterates Unicode glyphs that pdflatex lacks. - Runs pandoc with the
docs/pdf/templates:preamble.texas the in-header include,cover.texbefore the body, a table of contents, the Kartoza blue link colours and the Lato body font.
Keep PAGES in sync with the mkdocs nav
The PAGES array in lib/docs-pdf.sh must match the nav: section of
mkdocs.yml. When you add, remove or reorder a page, update both. If
you add a page to the nav but not to PAGES, it silently vanishes from
the PDF; the reverse feeds the PDF a page that no longer exists and the
build fails.
Why mermaid becomes a pointer in the PDF
Mermaid renders as live JavaScript on the site but pdflatex cannot draw it, so the transform swaps each diagram for a short note directing readers to the online handbook. This is why the architecture diagram lives on the web version and is referenced — not reproduced — in print.
The Kartoza credit¶
Per the brand guidelines, the handbook carries the credit triplet — Made with
💗 by Kartoza · Donate! · GitHub — in the MkDocs footer (via the copyright
setting in mkdocs.yml) and on the landing page. Preserve it when editing
those surfaces.