Deploying the docs site (Cloudflare Pages)¶
The docs site (this site) is built with Zensical and hosted on Cloudflare Pages. Static HTML, free tier, instant cache invalidation.
Local preview¶
Opens a hot-reloading dev server at http://localhost:8000/. Save any markdown file → page reloads. Change zensical.toml → restart.
Local build¶
Produces a static site under docs-site/site/. Open docs-site/site/index.html in your browser to verify.
First-time Cloudflare Pages setup¶
Done once per project; you can skip this section if the project already has a Pages site.
- Sign in to the Cloudflare dashboard.
- Workers & Pages → Create application → Pages → Connect to Git.
- Pick the GitHub repo (you'll authorise the Cloudflare GitHub app the first time).
- Configure build:
- Production branch:
main - Build command:
pip install zensical && cd docs-site && zensical build - Build output directory:
docs-site/site - Root directory (advanced): leave as the repo root.
- Environment variables (if needed):
PYTHON_VERSION = 3.12(Cloudflare's default Python is older; pin if you hit issues).- Save and Deploy.
The first build runs immediately. Subsequent deploys happen automatically on every push to main. Preview deploys happen on every PR — Cloudflare leaves a comment on the PR with the preview URL.
Custom domain¶
If you've configured docs.heymaud.com:
- Pages site → Custom domains → Set up a custom domain.
- Enter
docs.heymaud.com. - Cloudflare adds the CNAME for you (because the domain is on Cloudflare DNS already). If it isn't, follow the on-screen DNS instructions.
- Update the Cloudflare Access application to the new hostname — see Access protection. Skip this and the site goes public.
Access protection¶
The docs site is not public. It sits behind a Cloudflare Access self-hosted application (Zero Trust → Access → Applications → Maud docs) that challenges every visitor for a one-time email PIN and only admits the addresses listed in its Allow policy. Nothing in this repo enforces that — it lives entirely in the Cloudflare dashboard.
An Access application matches on hostname. That is the trap: when the
product was renamed and the docs moved to docs.heymaud.com, the existing
application kept guarding the old hostname and the new one shipped with no
protection at all. Nothing failed, nothing alerted; it was noticed by hand on
2026-09-13 and a new application created the same day.
So, whenever the docs hostname changes, updating the Access application's destination is part of the same change — not a follow-up. Add the new hostname to the app before flipping DNS, and remove the old one afterwards.
Checking it is still on¶
Healthy is a 302 to a *.cloudflareaccess.com/cdn-cgi/access/login/... URL.
A 200 means the site is open to the world — go and fix it before anything
else.
If it has lapsed¶
Zero Trust → Access → Applications → Add an application → Self-hosted:
- Name:
Maud docs. Destination: subdomaindocs, domainheymaud.com, path blank. - Policy: action Allow, include rule Emails → the addresses that should get in. Session duration: 1 month.
- Save. It is live immediately — no redeploy needed. Re-run the curl above.
PR preview deploys on *.pages.dev are on Cloudflare's domain, not ours, so
they are not covered by this application. Don't put anything in the docs
you would mind being on a preview URL.
What the docs may not contain¶
Access is a second line of defence, not a reason to relax the first: no credentials, keys, or default passwords in the docs — ever. Reference the secret by name and say where it lives (Fly secrets, the password manager). The one time the docs held a default password was also the window the site was open.
Workflow¶
The convenient cycle:
- Edit a markdown file in
docs-site/docs/. uvx zensical serveto preview.- Commit + push to a feature branch.
- Open a PR → Cloudflare leaves a preview-deploy comment within ~30 seconds.
- Merge → production updates within ~30 seconds.
When the build breaks¶
- 404 on a nav link — usually a typo in
zensical.toml'snavtable. Compare against the directory tree. pymdownx.somethingnot found — thepip install zensicalstep is incomplete; pin the Zensical version in the build command if you hit version drift.- Missing image / asset — paths in markdown are relative to the markdown file's location. Move or fix the path.
Reverting¶
Cloudflare keeps every deploy. Pages site → Deployments → Rollback restores any previous build with one click.