Documentation¶
This site is built with Zensical. The site is configured in
zensical.toml at the repository
root, and the page sources live as Markdown under docs/. This page explains how to preview, build,
and write those pages.
Preview locally¶
Run a local development server that watches the sources and reloads on every change:
The site is served at http://localhost:8000. To use another port, pass an explicit address with
-a:
Build the static site¶
To produce the static HTML without serving it, run the build:
The output is written to site/, which is gitignored. It is a build artifact, so it is never
committed; only the Markdown sources under docs/ and the zensical.toml config live in the
repository.
Publishing¶
The site is published automatically by .github/workflows/docs.yml. On pushes to
main that touch the docs sources, the workflow runs the build and deploys the result to GitHub
Pages:
The --locked flag fails if uv.lock is out of date, --no-build skips building the project
itself (only the docs group is needed), and --clean wipes the output directory before writing.
The published site lives at https://jbsilva.github.io/photo-tagger/.
Page structure¶
The navigation tree is defined by the nav table in zensical.toml, which maps each page title to
its source file. Adding a page means creating the Markdown file under docs/ and adding it to that
nav table.
Each page starts with a small block of YAML front matter that sets the page icon, followed by a single H1 heading and a short intro:
---
icon: lucide/book-open-text
---
# Page title
A one to three sentence intro that says what the page covers.
Authoring syntax¶
Beyond plain Markdown, the theme supports a few extensions. An admonition is a fenced callout; the body is indented four spaces after a blank line:
Content tabs group genuine alternatives behind labeled tabs:
Mermaid diagrams render from a fenced ```mermaid block, which is handy for flows on the
architecture pages:
```mermaid
flowchart LR
A[Read context] --> B[Build prompt] --> C[AI call] --> D[Write metadata]
```
Keeping the docs in sync with the code¶
Prose rots quietly: a flag gets renamed, a command gets added, and the pages keep describing the
tool as it was. scripts/check_docs_sync.py guards against that by walking the
live cyclopts app rather than a hand-maintained list, and it runs as a pre-commit hook whenever the
package or the docs change:
It enforces three rules:
- Every subcommand (
doctor,watch,undo,gui) is named inREADME.mdand in the CLI reference. - Every flag the CLI accepts appears in the CLI reference, under at least one of its names. That page promises to document every flag, so a new flag cannot ship undocumented.
- Every flag-shaped token in the user-facing pages (
README.md, the site index, and everything underusage/andgetting-started/, plus the telemetry and troubleshooting pages) is a flag the CLI really has. Lines that invoke another tool, such asuv sync --extra gui, are skipped.
The check is about coverage, not correctness: it cannot tell that a documented default is stale or that a description is now wrong. Environment variables and config keys are outside its reach too. When you change behavior rather than the flag surface, re-read the affected page yourself.
Style¶
Keep the prose consistent with the rest of the site:
- Hard-wrap prose and code at 100 columns.
- Use sentence-case headings ("Page structure", not "Page Structure"), with one H1 per page.
- Indent nested list items by four spaces.
- Link between pages with relative
.mdpaths, for example Testing or Installation. Use a#kebab-anchorto target a heading. - Link to source code with absolute GitHub URLs on
main, such aspipeline.py.
Tip
Preview the site with uv run --group docs zensical serve before you push. The local server catches
broken links and rendering mistakes that are easy to miss in raw Markdown, and the docs deploy runs
automatically once your change lands on main.