Zensical Customizer
Zensical is the successor to Material for MkDocs, built by the same team. Config file:
zensical.toml (TOML format, all settings under [project]). Template engine: MiniJinja (Rust).
Dev server: uv run poe docs-serve. Build: uv run poe docs-build.
Use DeepWiki (mcp__deepwiki__ask_question with repo zensical/zensical) for questions about
Zensical internals not covered here.
Decision Tree
- •
Add styles to existing pages -> Edit
docs/stylesheets/extra.cssor create a new stylesheet and register inextra_css. See project-setup.md. - •
Add JavaScript to all pages -> Place script in
docs/javascripts/, register inextra_javascriptinzensical.toml. See javascript.md. - •
Add interactive widget to specific page -> Add
<div id="mount">in markdown, create JS that usesdocument$to mount on that element. See "Pattern 1" in javascript.md. - •
Create a fully custom page layout -> Set up
overrides/directory, create custom template extendingbase.html, reference via page frontmattertemplate:field. See templates.md. - •
Override header/footer/nav -> Override partials in
overrides/partials/. See "Overridable Partials" in templates.md. - •
Embed a JS framework app (React, Vue, Svelte) -> Build externally, output bundle to
docs/javascripts/, mount viadocument$or custom template. See "Pattern 2" and "Pattern 3" in javascript.md.
Quick Start: Add an Interactive Page
Step 1: Enable template overrides (one-time)
Add to zensical.toml under [project.theme]:
custom_dir = "overrides"
Create the directory: overrides/
Step 2: Create a custom template
Create overrides/interactive.html:
{% extends "base.html" %}
{% block content %}
{{ page.content }}
<div id="app-mount"></div>
{% endblock %}
{% block scripts %}
{{ super() }}
<script type="module" src="{{ base_url }}/javascripts/my-app.js"></script>
{% endblock %}
Step 3: Create the page
Create a markdown file (e.g., docs/demos/my-demo.md):
--- template: interactive.html icon: lucide/play --- # Interactive Demo Description of the demo.
Step 4: Add JavaScript
Place docs/javascripts/my-app.js with initialization logic.
Step 5: Register in navigation
Add to nav in zensical.toml:
{ "Demos" = ["demos/my-demo.md"] },
Key Constraints
- •No full plugin/module system - extensibility is limited to templates, JS, CSS
- •MiniJinja, not Jinja2 - mostly compatible, but complex Jinja2 patterns may differ
- •125% root font-size - Zensical sets
html { font-size: 125% }(20px); third-party libraries with rem-based sizing render 25% larger. Fix with explicit pixel values. - •Markdown extensions are all-or-nothing - defining any custom extensions requires configuring ALL extensions (defaults don't apply partially)
- •
navigation.instantnot enabled in this project -window.loadworks for site-wide scripts, but page-specific widgets should still usedocument$for forward compatibility
References
- •templates.md - Template blocks, custom page templates, partials, context variables, MiniJinja syntax
- •javascript.md - JS/CSS injection, document$ observable, instant navigation, interactive component patterns
- •project-setup.md - This project's directory structure, existing customizations, ISCC brand colors, Zensical quirks