# Documentation

The site is built with [Zensical](<https://zensical.org>) from `zensical.toml` and the Markdown pages in `docs/site/`. `docs/SEMANTICS.md`, `docs/MIGRATING.md` and the journal in `docs/journal/` stay where they are, and the site links to them.

## Building locally

```sh
just docs-serve   # build, serve on http://localhost:8000/wend/, rebuild on change
just docs-build   # a clean, strict build into site/
just docs-check   # the build, then check_site.py and the examples
```

The toolchain is pinned in `.just/docs.just` and in `.github/workflows/site.yml`; change both together. It is not part of the project's dependencies.

## The API reference

The pages in `docs/site/reference/api/` are generated by [mkdocstrings](<https://mkdocstrings.github.io/python/>) from the source in `src/wend/`, by static analysis with griffe. Building the reference does not import wend or its optional dependencies.

- `filters = "public"` follows each module's `__all__`, and names without a leading underscore where a module has none.
- Docstrings are Markdown in the Google style: `Args:`, `Returns:`, `Raises:` and `Examples:` sections. Link to another object with `[name][wend.Name]`.
- `docs/scripts/griffe_wend.py` removes special methods that only implement object protocols (`__repr__`, `__eq__`, ...), and works around a griffe bug with nested t-strings.

## Checks

`--strict` fails the build on a broken link, anchor or cross-reference. griffe's docstring warnings do not fail it, so the workflow fails on any line of the build log that starts with `griffe:`. Then `docs/scripts/check_site.py` checks that:

- every Markdown page under `docs/site/` is in the nav, and every nav entry exists;
- every internal link and anchor in the built site resolves;
- every page is listed in the `llmstxt` sections of `zensical.toml`, with the same description as its front matter, and has a Markdown copy;
- every name in each public module's `__all__` has an entry in the API reference.

## Examples are tests

`uv run pytest docs` runs the code on every page: each page is one test, and its `python` and `pycon` blocks run in order in one namespace, in a fresh temporary working directory. A `pycon` block is a doctest, so its output must match. A block whose info string contains `notest` is skipped. A fenced block inside an HTML comment runs but is not shown, which suits setup such as creating the files an example reads.

## Agents and llms.txt

The `llmstxt` plugin writes `llms.txt` (an index of the pages, with their descriptions), `llms-full.txt` (every listed page, including the API reference, as Markdown) and a Markdown copy of each page at `<page>/index.md`, linked from the page's head. Each page also has a "Copy as Markdown" action.

## Publishing

`.github/workflows/site.yml` builds the site on every pull request that touches it and on every push to master.

- **Production:** a push to master publishes to the root of the `gh-pages` branch, which GitHub Pages serves at [https://lmmx.github.io/wend/](<https://lmmx.github.io/wend/>).
- **Previews:** a pull request from this repository gets a preview at `https://lmmx.github.io/wend/pr-preview/pr-<number>/`, linked from a comment on the pull request. It is updated on every push and removed when the pull request closes. Previews are deployed only once Pages serves the `gh-pages` branch.
