Source for lyndsysimon.com, built with
Zensical. Content lives in src/, posts in
src/posts/.
Add a Markdown file to src/posts/. It needs a date in the front matter, and
the URL is derived from the post title unless a slug is given:
--- date: 2026-11-05 categories: - Software slug: some_post # optional; defaults to a slugified title --- # Post title The introduction, which is what shows up on the home page listing. <!-- more --> Everything after the `<!-- more -->` marker only appears on the post page.
The home page, /archive/, and /category/ are generated by the blog plugin —
nothing has to be updated by hand. src/index.md is intentionally empty: it is
the blog's entry point, so whatever it contains is printed above the newest
post. The tags plugin is switched off and there is no /tags/ page; tags: in
front matter is inert.
A fenced mermaid block is rendered to SVG by Pele, not
Mermaid.js — Pele is ~270 kB gzipped against Mermaid's ~1.6 MB, has no
dependencies, and themes from the site's CSS variables.
```mermaid flowchart LR A[Start] --> B{Done?} ```
Pele is vendored at src/javascripts/pele.global.js (MIT, licence alongside it)
and loaded lazily, so pages without a diagram never download it. The fence is
emitted as <pre class="pele">; do not change that class to mermaid or
Zensical's own handler starts fetching Mermaid from unpkg. A diagram Pele cannot
parse falls back to showing its source as a code block.
blog_dir = "."andpost_url_format = "posts/{slug}"together are what keep post URLs at/posts/<slug>/. Zensical looks for posts in<blog_dir>/posts/, so changingblog_dirtopostsmakes it find nothing at all, and dropping the prefix frompost_url_formatmoves every post to/<slug>/. Both break published links.- Posts with a
sluguse it verbatim, which is how the older posts kept their underscore URLs from the MkDocs days. New posts without aslugget a hyphenated URL derived from the title.
uv sync uv run zensical serve -a 127.0.0.1:9124
Mission Control runs this as the "Blog" service on port 9124.
uv run zensical build python3 scripts/postprocess.py site python3 scripts/check_links.py site
scripts/postprocess.py is not optional. The blog plugin emits every heading in
a listing as <h2><a class="toclink">…</a></h2>, which both makes the title look
like a link and, inside a post excerpt, turns the post's own subheadings into
links. The script moves the anchor out to a small link icon after the heading
text. It is idempotent and matches on the toclink class, so an upstream markup
change degrades to "headings are plain text" rather than breaking the build.
Pushing to main runs the same build in GitHub Actions and deploys to GitHub
Pages.
- Set up RSS for the blog plugin
- Write a plugin (or contibute support to Pygments) for OpenSCAD