1. Installing Zensical, and the Failure That Hits Most Macs
pip install zensical succeeds on a stock Mac and gives you nothing. A 1.0 kB wheel, version 0.0.2, no binary. Here is why, and the working install.
The WJS Desk
Sep 22, 2026 · updated 2 days ago · 7 min read

Zensical is a static site generator written in Rust by the people behind Material for MkDocs, which is the theme a very large share of open source documentation already runs on. It hit 5,748 stars, it is MIT licensed, and the last commit was three days before we wrote this.
We installed it, built a 203 page site with it, tried to migrate an existing MkDocs project, and deliberately broke it five ways. This part covers getting it running, including the failure that will hit most Mac users in the first thirty seconds.
The install that silently does nothing
Here is the obvious command, run in a clean virtual environment on a stock Mac:
python3 -m venv .venv
./.venv/bin/pip install zensical
It succeeds. Four seconds, no errors, no warnings:
Downloading zensical-0.0.2-py2.py3-none-any.whl (1.0 kB)
Installing collected packages: zensical
Successfully installed zensical-0.0.2
Then nothing works, because there is no zensical binary anywhere in the environment.
Look at the two numbers in that output. It installed version 0.0.2, and the wheel was 1.0 kB. The current release is 0.0.63 and its macOS wheel is 13.7 MB. What got installed was a placeholder from early in the project's life.
Why it happens, and it is not zensical's fault
Zensical declares requires_python = ">=3.10". The Python that ships with macOS Command Line Tools is 3.9.6.
When pip cannot satisfy a version constraint, it does not stop. It walks backwards through the release history looking for the newest version that will install on your interpreter, and here that is 0.0.2, published before the project set a floor. So pip does exactly what it was designed to do and hands you a stub.
This failure mode is worth internalising beyond this tool. A successful pip install is not evidence you installed the thing you asked for. Any package that raised its Python floor after publishing early releases can do this to you, and the only visible symptom is a version number you were not reading and a missing command.
Check before you debug anything else:
./.venv/bin/pip show zensical | grep Version
python3 --version
If the version is not in the 0.0.6x range, your Python is too old. Nothing else in this series will work until that is fixed.
Installing it properly
Point the virtual environment at a Python 3.10 or newer. On this machine 3.12 was already present:
python3.12 -m venv .venv
./.venv/bin/pip install zensical
Five seconds, and now you get the real thing:
Name: zensical
Version: 0.0.63
If you have no 3.10+ available, brew install python@3.12 or any pyenv-managed interpreter works. The wheel is prebuilt for macOS on both Intel and Apple silicon, Linux on x86_64, aarch64 and armv7, and musl, so nothing compiles at install time despite the Rust core. That is why a 13.7 MB download finishes in five seconds.
What you actually get
$ zensical --help
Commands:
build Build a project.
new Create a new template project in the current or given directory.
serve Build and serve a project.
Three commands. That is the whole surface area, and it is worth pausing on, because the closest comparison most readers will have is MkDocs plus a theme plus a plugin list plus a Python dependency tree. This is one binary behind a thin Python wrapper.
Prerequisites, honestly stated
What you actually need before starting, and roughly what it costs:
| Requirement | Note |
|---|---|
| Python 3.10 or newer | The one thing that will stop you. macOS ships 3.9.6 |
| Disk | About 40 MB for the wheel unpacked |
| Rust toolchain | Not needed. Wheels are prebuilt |
| Node | Not needed |
| Time to first built page | Under two minutes if your Python is right |
That third row is worth dwelling on. The tool is written in Rust and you never see Rust: no cargo, no compiler, no waiting. The maintainers publish wheels for macOS on Intel and Apple silicon, Linux on x86_64, aarch64 and armv7, plus musl variants, which covers essentially every machine you would run docs on including Alpine containers.
Your first site
mkdir site && cd site
zensical new .
It prints nothing at all on success, which is disconcerting the first time. Here is everything it created:
.github/workflows/docs.yml
docs/index.md
docs/markdown.md
zensical.toml
Four files, and one of them is a GitHub Actions workflow. Scaffolding your deployment pipeline on new is an opinionated choice and a good one; we cover what is actually in that workflow, and the problem with it, in part 4.
The config is TOML rather than the YAML MkDocs uses:
[project]
site_url = "https://www.example.com/"
site_name = "Documentation"
nav = [
{ "Get started" = "index.md" },
{ "Markdown in 5min" = "markdown.md" },
]
[project.theme]
language = "en"
Most of the scaffolded file is commented-out options: site_description, repo_url, edit_uri, extra_css, favicon. Anyone who has written an mkdocs.yml will recognise every key, which is not an accident and is the subject of part 3.
Build it
$ zensical build
Build started
No issues found
Build finished in 0.29s
Three pages in 0.29 seconds. But time the whole command rather than trusting the number it prints:
| Measurement | Time |
|---|---|
| What zensical reports | 290 ms |
| Actual wall clock | 1,711 ms |
The missing 1.4 seconds is Python interpreter startup plus loading the extension module. The Rust core is genuinely fast and the number it prints is honest about the Rust core; it is just not the number you experience. Part 2 shows why this gap matters less than it looks, because it turns out to be almost entirely fixed cost.
Serve it
$ zensical serve -a localhost:8899
Serving /path/to/site on http://localhost:8899
Build started
No issues found
We checked it with curl rather than by eye. The root returned HTTP 200 in 0.95 ms, a deep page at /gen/page-050/ also returned 200, and the served HTML contains a live reload hook, so edits refresh the browser without you touching it.
Useful flags: -o opens your browser, -a sets the address, -f points at a config file elsewhere. There is also -s, --strict, and its help text reads "Strict mode (currently unsupported)". Remember that line. It is the subject of part 4 and it is the single biggest limitation in the tool right now.
What broke, and what did not
Two things worth reporting from this stage.
The Python floor. Covered above, and it cost us the first attempt entirely. On a machine with only the system Python, the documented install command produces a working-looking environment with no working program.
Silence on success. zensical new . printing nothing is technically fine and briefly confusing. Run find . -type f after it to confirm rather than assuming it failed.
Against that, the parts that could have gone wrong and did not: no compilation step, no dependency resolution beyond the single wheel, no Node toolchain, no theme to install separately, and the dev server came up first try.
Where it puts things, and what it does not touch
Worth knowing before you point it at a real repository, because a generator that writes in unexpected places is a generator you cannot put in CI.
| Path | What it is |
|---|---|
docs/ | Your markdown. The only input directory |
zensical.toml | Config, at the project root |
site/ | Build output. Gitignore this |
.github/workflows/docs.yml | Scaffolded deploy pipeline |
Nothing is written to your home directory, no global config is created, and no cache appears outside the project. That is a lower footprint than most toolchains in this space and it makes the tool trivially safe to evaluate.
One thing the scaffold does not do: add site/ to a .gitignore. If you run zensical new . inside an existing repository, your first build drops several hundred files into the working tree and git status becomes unreadable. One line fixes it and you have to know to write it:
echo "site/" >> .gitignore
A note on the version number
The current release is 0.0.63. Not 1.x, not even 0.1. That is the maintainers being accurate rather than modest, and you should read it literally.
Some evidence for how young it is, from the repository itself: 5,748 stars against 34 watchers, which is an unusually wide ratio and tells you most of those stars are bookmarks rather than users. It also has 1 open issue, which for a project this visible means either exceptional triage or not enough people using it hard enough to file things. Given the age, we would guess the second.
None of that is a reason to avoid it. It is a reason to keep your markdown portable and not build tooling that assumes this specific generator, which is advice we would give about any 0.0.x dependency.
Rolling it back
Everything here lives in one virtual environment and one directory:
rm -rf .venv site
Nothing is installed globally, nothing touches your shell profile, and no configuration is written outside the project. If you decide against it after part 2, that command is the whole uninstall.
Next
Part 2 takes it from a three page demo to 203 pages and 220,000 words, and measures what actually happens to build times, output size, and the search index you are about to ship to every visitor.


