# Zensical: Documentation Generator

`Zensical` is a fast static documentation site generator written in Rust and Python by the creators of Material for MkDocs and mkdocstrings. It configures documentation via typed `zensical.toml` files, replacing legacy `mkdocs.yml` setups.

## What It Does

Zensical generates static technical documentation sites with sub-second live reloading. It automates API documentation via `mkdocstrings[python]`, client-side MathJax LaTeX rendering, dynamic code execution through `markdown-exec`, and native Mermaid diagram support.

It also compiles machine-readable `site/llms.txt` and `site/llms-full.txt` feeds, allowing AI coding assistants to consume the library's entire API reference surface and guides in a single, high-signal contextual payload.

## Why It's in Zenith

Zenith chooses Zensical because it standardizes on TOML configuration (`zensical.toml`), avoiding YAML sprawl and unifying configuration patterns with `pyproject.toml`.

With strict validation enabled (`zensical build --strict`), deployments fail automatically if an internal link, anchor tag, footnote, or cross-reference is broken. Designed for dual human and AI consumption, Zensical pairs modern responsive theming with automated machine-readable feeds.

## Integrated Plugins

Zenith enhances Zensical with specialized plugins configured under `[project.plugins]`:

| Plugin | Capability | Purpose in Zenith |
| --- | --- | --- |
| **`gh-admonitions`** | GitHub Alert Callouts | Renders GitHub-flavored alert callouts (`> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]`) with styled border accents and icons. |
| **`llmstxt`** | AI Context Manifests | Compiles structured `site/llms.txt` and `site/llms-full.txt` feeds, allowing AI coding assistants to consume repository guides and API signatures in a single contextual payload. |
| **`markdown-exec`** | Dynamic Code Execution | Executes inline Python, Shell, Tree, and Markdown snippets (`python exec="1"`, `sh exec="1"`) during build, ensuring rendered tool configurations and directory trees reflect live repository files without manual copying. |
| **`mkdocstrings[python]`** | Automated API Documentation | Extracts and documents public Python functions, classes, type parameters, and protocols directly from source code docstrings via Griffe with NumPy style parsing. |

## Markdown Extensions Suite

Zenith enables a suite of Python-Markdown and PyMdown Extensions under `[project.markdown_extensions]` to support rich technical authoring:

| Extension Category | Extensions | Enabled Features |
| --- | --- | --- |
| **Callouts &amp; Blocks** | `admonition`, `pymdownx.details` | Collapsible `<details>` blocks (`??? note "Title"`), inline notes, and standard warning callouts. |
| **Code &amp; Diagrams** | `pymdownx.superfences`, `pymdownx.highlight`, `pymdownx.inlinehilite` | Custom fences for interactive **[Mermaid](<https://mermaid.js.org/>)** diagrams, line numbers (`anchor_linenums`), syntax highlighting, and inline code formatting (`#!python`). |
| **Math &amp; Symbols** | `pymdownx.arithmatex`, `pymdownx.emoji`, `pymdownx.smartsymbols` | Client-side **[MathJax](<https://www.mathjax.org/>)** LaTeX formula rendering (`\( ... \)` and `$$ ... $$`), Twemoji SVG emojis (`:octicons-code-24:`), and typographic arrows. |
| **Interactive UI** | `pymdownx.tabbed`, `pymdownx.tasklist`, `zensical.extensions.preview` | Multi-language tabbed code switchers (`=== "Python"`), interactive task checkboxes (`- [x]`), and instant link hover previews. |
| **Typography &amp; Structure** | `attr_list`, `def_list`, `footnotes`, `abbr`, `toc` | HTML attribute attaching (`{: .grid .cards }`), definition lists, footnotes (`[^1]`), glossary tooltips, and permalink anchors. |
| **Content Reuse** | `pymdownx.snippets` | Transclusion of external files and code extracts directly into documentation (`--8<-- "path/to/file"`). |

## Configuration in Zenith

Configured in `zensical.toml` at the project root:

```toml
# ==============================================================================
# Zensical Configuration (zensical.toml)
#
# Tool: Zensical (https://github.com/zensical/zensical)
# Purpose: Modern, fast static documentation site generator configured with TOML.
# Why it's in Zenith: Provides instant live-reloading documentation with native
# dark/light/system mode switching, Lucide icons, Mermaid diagrams, client-side
# MathJax integration for LaTeX math, markdown-exec for dynamic code execution,
# and mkdocstrings for automated Python API documentation generation.
# ==============================================================================

[project]
    edit_uri         = "edit/main/docs/"
    repo_name        = "{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}"
    repo_url         = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}"
    site_author      = "{{ cookiecutter.author_name }}"
    site_description = "{{ cookiecutter.description }}"
    site_name        = "{{ cookiecutter.project_name }}"
    site_url         = "https://{{ cookiecutter.github_username }}.github.io/{{ cookiecutter.project_slug }}/"

    nav = [
        { "Overview" = "index.md" },
        { "Getting Started" = "getting-started.md" },
        { "Reference" = "reference.md" },
        { "Architecture (ADRs)" = [
            "adr/index.md",
            { "ADR-0001: Record Architecture Decisions" = "adr/0001-record-architecture-decisions.md" },
        ] },
        { "Changelog" = "changelog.md" },
    ]

    extra_css = [
        "stylesheets/palette.css",
        "stylesheets/custom.css",
        {% if cookiecutter.include_cli in [True, "yes", "true", "True", "1"] %}
        "stylesheets/termynal.css",
        {% endif %}
    ]

    extra_javascript = [
        "javascripts/mathjax.js",
        "https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js",
        {% if cookiecutter.include_cli in [True, "yes", "true", "True", "1"] %}
        "javascripts/termynal.js",
        {% endif %}
    ]

    [project.validation]
        invalid_links         = true
        invalid_link_anchors  = true
        shadowed_definitions  = true
        shadowed_footnotes    = true
        unresolved_footnotes  = true
        unresolved_references = true
        unused_definitions    = true
        unused_footnotes      = true

    [project.theme]
        features = [
            "announce.dismiss",
            "content.action.edit",
            "content.action.view",
            "content.code.annotate",
            "content.code.copy",
            "content.code.select",
            "content.footnote.tooltips",
            "content.tabs.link",
            "content.tooltips",
            "navigation.footer",
            "navigation.indexes",
            "navigation.instant",
            "navigation.instant.prefetch",
            "navigation.instant.preview",
            "navigation.path",
            "navigation.top",
            "navigation.tracking",
            "search.highlight",
            "search.suggest",
            "toc.follow",
        ]
        language = "en"
        logo = "assets/python-logo.svg"

        [[project.theme.palette]]
            media       = "(prefers-color-scheme)"
            toggle.icon = "lucide/sun-moon"
            toggle.name = "Switch to light mode"

        [[project.theme.palette]]
            media       = "(prefers-color-scheme: light)"
            scheme      = "default"
            toggle.icon = "lucide/sun"
            toggle.name = "Switch to dark mode"

        [[project.theme.palette]]
            media       = "(prefers-color-scheme: dark)"
            scheme      = "slate"
            toggle.icon = "lucide/moon"
            toggle.name = "Switch to system preference"

    [[project.extra.social]]
        icon = "fontawesome/brands/github"
        link = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}"

    [project.markdown_extensions]
        abbr = {}
        admonition = {}
        attr_list = {}
        def_list = {}
        footnotes = {}
        md_in_html = {}
        pymdownx.arithmatex.generic = true
        pymdownx.betterem = {}
        pymdownx.caret = {}
        pymdownx.details = {}
        pymdownx.emoji.emoji_generator = "zensical.extensions.emoji.to_svg"
        pymdownx.emoji.emoji_index = "zensical.extensions.emoji.twemoji"
        pymdownx.highlight.anchor_linenums = true
        pymdownx.highlight.line_spans = "__span"
        pymdownx.highlight.pygments_lang_class = true
        pymdownx.inlinehilite = {}
        pymdownx.keys = {}
        pymdownx.magiclink = {}
        pymdownx.mark = {}
        pymdownx.smartsymbols = {}
        pymdownx.snippets.check_paths = true
        pymdownx.snippets.dedent_subsections = true
        pymdownx.superfences.custom_fences = [
            { name = "mermaid", class = "mermaid", format = "pymdownx.superfences.fence_code_format" },
            { name = "tree", class = "tree", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
            { name = "markdown", class = "markdown", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
            { name = "md", class = "md", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
            { name = "python", class = "python", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
            { name = "bash", class = "bash", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
            { name = "sh", class = "sh", validator = "markdown_exec.validator", format = "markdown_exec.formatter" },
        ]
        pymdownx.tabbed.alternate_style = true
        pymdownx.tabbed.combine_header_slug = true
        pymdownx.tasklist.custom_checkbox = true
        pymdownx.tilde = {}
        toc.permalink = true
        zensical.extensions.preview.targets.include = ["*"]

    [project.plugins.gh-admonitions]

    [project.plugins.llmstxt]
        full_output = "llms-full.txt"

        [project.plugins.llmstxt.sections]
            "Documentation" = [
                "index.md",
                "getting-started.md",
                "reference.md",
                "adr/index.md",
                "adr/0001-record-architecture-decisions.md",
                "changelog.md",
            ]

    [project.plugins.markdown-exec]

    [project.plugins.mkdocstrings]
        default_handler = "python"

    [project.plugins.mkdocstrings.handlers.python]
        inventories = ["https://docs.python.org/3/objects.inv"]
        paths = ["src"]
        options.annotations_path = "brief"
        options.backlinks = "tree"
        options.docstring_options.ignore_init_summary = true
        options.docstring_style = "numpy"
        options.extensions = ["griffe_warnings_deprecated"]
        options.line_length = 88
        options.members_order = "source"
        options.merge_init_into_class = true
        options.parameter_headings = true
        options.relative_crossrefs = true
        options.scoped_crossrefs = true
        options.separate_signature = true
        options.show_bases = true
        options.show_inheritance_diagram = true
        options.show_root_heading = true
        options.show_signature_annotations = true
        options.show_signature_type_parameters = true
        options.show_source = true
        options.show_symbol_type_heading = true
        options.show_symbol_type_toc = true
        options.signature_crossrefs = true
        options.summary = true
        options.type_parameter_headings = true
        options.unwrap_annotated = true
```

## Key Invocations

```bash
uv run poe docs-serve                  # Start live-reloading dev server (localhost:8000)
uv run zensical serve -a 0.0.0.0:8080  # Bind to custom host address and port
uv run zensical serve -o               # Open browser preview automatically
uv run poe docs-build                  # Strict production build into site/
```

### Live Reloading Watchdog

`zensical serve` includes an integrated file watchdog:

- **Instant Millisecond Rebuilds**: Monitors `docs/`, `zensical.toml`, assets, and stylesheets, updating pages in milliseconds as Markdown files are modified.
- **WebSocket Live Browser Sync**: Automatically pushes updates to all open browser tabs without manual page refreshes.
- **Agent Workflow Note**: When developers run `uv run poe docs-serve` in a terminal window, AI agents do not need to execute rebuilds during editing turns because the watchdog reloads pages automatically.

## Upstream Documentation

- [Zensical GitHub Repository](<https://github.com/zensical/zensical>)
- [mkdocstrings Documentation](<https://mkdocstrings.github.io/>)
- [Material for MkDocs Guide](<https://squidfunk.github.io/mkdocs-material/>)
