# Documentation

The site is built with [Zensical](<https://zensical.org/>) from `docs/site/` and `zensical.toml`. The Python API reference is generated by mkdocstrings from the package's docstrings and the compiled module's stub (`python/mibz2/_mibz2.pyi`).

```sh
just docs-serve   # build, serve and rebuild on change
just docs-check   # strict build, site checks, and the pages' examples as tests
```

- `docs/scripts/check_site.py` checks that every page is in the nav, that internal links and anchors resolve, that every page has a description matching its llms.txt entry, and that every public name is in the API reference.
- `docs/conftest.py` runs each page's Python examples with pytest (`pytest docs/site`); a `pycon` block's output must match.
- `docs/scripts/bench_history.py` turns the `bench-results` branch into the benchmark pages' data (`docs/site/assets/bench-history.json`) and tables (`docs/generated/`) before each build. Without a checkout of the branch (`--store`), it reads `origin/bench-results`, or writes empty ones.
- `docs/site/assets/data/lane-sweeps.json` holds the measured walk timings by lane count that [Why 32 couriers beat one](<https://lmmx.github.io/mibz2/concepts/couriers/#lane-counts>) draws (`assets/javascripts/couriers.js`). It is written by hand, from the record: one panel a sweep, each with its own axes, its points (`x`, `y`, and optionally `lo` and `hi` for an interval) and its source. A new sweep is a new panel; the page draws every panel. Only measured points go in it.

## Publishing

`.github/workflows/site.yml` builds the site on every push to master, and after each Benchmark run on master, and publishes it to the `gh-pages` branch, served at [https://lmmx.github.io/mibz2/](<https://lmmx.github.io/mibz2/>). A pull request from this repository gets a preview under `pr-preview/pr-<number>/`, linked from a comment on the pull request and removed when it closes. Previews start once the repository's Pages source is set to the `gh-pages` branch.
