Colophon
None of the code or prose on this site has been or will be generated with the assistance of a LLM.
The site doesn't use resources from other domains and there are no referral links or cookies. Most pages only load two resources by default: the HTML itself and the stylesheet. The logo and other icons are stored as SVG data URIs in the CSS.
The only analytics are from my hosting provider, Netlify, which ostensibly uses log scraping. JavaScript is only loaded and run on-demand after clicking on the search icon.
Internals
This site is generated from folders containing Markdown files. The structure looks like this:
/pages/colophon.md
/pages/...
/articles/index.md
/articles/<year>/<month>-<day>-<time>-<short-name>.md
/articles/...
/series/updates/index.md
/series/updates/<year>-<month>-<day>-<time>-<short-name>.md
/series/...
/notes/<subtopic>/<note>.md
/notes/...
/static/style.css
/static/...
It's easy to update this site with a basic text editor, as opposed to a web interface normally found in blog engines.
Markdown makes adding emphasis, code, headings, and links easy. Notes have a front-matter section with the date they were last updated and other metadata, like the epistemic status and effort. I wish they didn't need this (it's a bit clunky to have this information "above the fold"), but I haven't come up with a better way to assign metadata yet.
The site generator is called lift11 Because it converts Markdown to markup. and is written in Zig.
It's written in Zig with zero dependencies outside of the standard library.
Instead of a full-fledged Markdown parser, it supports a subset of Markdown called "Mindown."
Processing the most expensive note into HTML takes about 300µs on my MacBook Air M2 (2ms with search indexing).
The entire build takes less than 20ms on my machine.
A thread pool processes most files concurrently22 But not even close to achieving decent speedups.
Article conversion is still single-threaded..
Here's the output of lift when run on this site:
notes: 97 (399.5 KiB) 14.34 ms ( 75%): 147.9 µs/elt, 27.85 MiBps
/ md: 97 (399.5 KiB) 42.54 ms (297%): 438.5 µs/elt, 9.39 MiBps
entries: 4 ( 14.4 KiB) 1.94 ms ( 10%): 485.6 µs/elt, 7.39 MiBps
pages: 6 ( 22.6 KiB) 0.39 ms ( 2%): 64.2 µs/elt, 58.72 MiBps
static: 6 ( 35.4 KiB) 0.38 ms ( 2%): 62.7 µs/elt, 94.19 MiBps
search: 101 (413.9 KiB) 1.89 ms ( 10%): 18.7 µs/elt, 219.26 MiBps
total: 113 (471.9 KiB) 19.00 ms (100%): 168.2 µs/elt, 24.84 MiBps
cpu-usr: 22.58 ms ( 30%)
cpu-sys: 53.61 ms ( 70%)
1.04 ms / 15.1 KiB: Bicycle safety
1.10 ms / 7.5 KiB: Modern nvi mappings
1.12 ms / 17.4 KiB: Using Ansible and Docker for home servers
1.57 ms / 11.8 KiB: The Rheem ProTerra hybrid heat pump water heater
1.82 ms / 13.1 KiB: Web reading list
The site-out directory holds the HTML and CSS results of generating the website and is pushed to GitHub, which Netlify makes available across the internet.
The HTML and CSS are small enough to leave un-minified, so it's easier to inspect for curious visitors.
Another site-assets directory mirrors the site-out structure for notes and articles that display images.
A Retrobatch workflow compresses and rescales any source photos or computer screenshots from a site-originals directory.
Search
Search is implemented with framework-less JavaScript that's injected into the document in the search icon's onclick handler.
If JavaScript is disabled, the search icon is hidden.
The handler presents a modal <dialog> search form and loads a JSON list of all the documents available on the site.
As the user types in the dialog form, the JavaScript uses the Porter stemming algorithm to compute word stems.
It also loads JSON with all stems with the same initial letter mapped to a list of documents and their rankings.
The rankings use the BM25 ranking algorithm and are generated by lift while parsing Mindown.
Here's the pattern of JSON files in the search/ subdirectory:
/search/documents.json
/search/a.json
/search/b.json
/search/...
Updated on 12 May 2026.