Changelog

Kolofon · 10 September 2026

0.11.40 – 0.11.68 — twenty-nine releases, one entry

when it turned out the changelog had stopped at 0.11.39 while the engine was twenty-nine releases further on

0.11.40 – 0.11.68 — twenty-nine releases, one entry

Text: Kolofon

The rule in this project is that every change to engine code is a new release, and every release gets a changelog entry. The first half held. The second stopped on 8 September at 0.11.39 and did not move for three days, during which twenty-nine further versions shipped.

Writing twenty-nine entries after the fact was an option. They would have been dishonest — composed from memory, each pretending to be a note taken at the moment of release. This entry stands in their place and pretends to be nothing other than what it is: catching up.

THE REGISTRATION WALL AND READER ACCOUNTS (0.11.40 – 0.11.59)

The largest block, and the only one that changes what a reader sees on the first screen. A post can carry a threshold: the rest is for readers with an account. The account is free, an email address creates it, and signing in happens through a link in the inbox — no password, because a password that does not exist cannot be stolen.

A dozen or so fixes grew around this, each of them out of one specific situation. The teaser now shows a fraction of the text instead of breaking off mid-sentence. An image behind the wall fades into a gradient and carries a button. Returning after sign-in leads back to the post you started from rather than to the home page — first through an address in the link, then, once that proved unreliable, through an address stored alongside the token on the server.

Consent to mailing was built separately: a field, a switch on the account page, a timestamp and the version of the terms the consent was given against. Consent without a recorded document version is useless the moment the document changes.

And one thing that had to be fixed twice, because the first attempt went too shallow: attaching a reader's earlier activity to a freshly created account. The first version relied on a browser identifier supplied by the client. The second binds the identifier to the sign-in token and performs the whole operation server-side, along a single path.

CODE AND LOG BLOCKS (0.11.60 – 0.11.61)

Until 0.11.60 post content was an array of strings, and every string rendered as a paragraph. That was enough for the prose the engine was built for. It is not enough for technical writing: a fragment of code pasted into a paragraph loses its indentation, breaks in arbitrary places and blends into the narrative.

A content item may now be an object — a code block, a console window or a heading. The extension is backwards compatible, so instances whose content is all strings noticed nothing. Syntax highlighting was written from scratch rather than pulled from a library: highlight.js is tens of kilobytes in a worker bundle in exchange for recognising strings, comments, numbers and a keyword list, and it brings a palette of its own that argues with the instance theme.

There are two console windows — black for a Unix shell, navy for PowerShell. Those two colours are hard-coded rather than taken from the theme, and deliberately so: that is how those windows look on everyone's machine, which makes them a quotation from reality rather than an aesthetic decision belonging to the instance.

In 0.11.61 paragraphs gained justified setting with hyphenation. Hyphenation is not decoration here: Polish has long words, and justification without breaking them stretches the spaces until rivers of white run down the column. Below thirty rem justification switches off, because a narrow column on a phone carries it worse than a wide one.

BRAND NAMES LEAVE THE ENGINE (0.11.62)

The most embarrassing release of the series. The engine's default interface strings carried the proper names of one instance — in the sentence about mailing consent and in the description of the basic account. Default values compile together with the code, so they travelled into the browser bundle of EVERY instance, including those they had nothing to do with.

The existing guard had no way of catching this: it makes sure strings do not sit inside components, and the string dictionary is precisely where strings are allowed to sit. The new guard works from two directions. Heuristically it looks for a capitalised word in the middle of a sentence — which catches a brand it has never heard of. On top of that it reads names out of the configuration of whichever instances it is pointed at: brand, author and domain. Adding a new instance widens the protection by itself, with no edit to the script.

RELEASE PROPAGATION (0.11.63, 0.11.68)

The engine lives in its own repository but runs inside instances. Until now it was pulled across by hand, and forgotten about with some regularity — two instances sat on 0.11.39 while the engine was at 0.11.62, twenty-three releases behind.

A release tag now triggers a workflow that, for each instance, copies the files listed in the manifest, runs the guards and opens a pull request. It neither merges nor deploys — a new release may require interface strings to be filled in on the instance side, and no automation can guess those for a person. A green result opens an ordinary pull request, a red one a draft describing what is missing.

The first version had a flaw that only shows at pace: it named the branch after the release, so every release opened a fresh set of pull requests while the previous ones stayed open. Five releases in an hour left twenty-two open pull requests and flooded an inbox with notifications. In 0.11.68 the branch always carries the same name, and a new release updates the existing pull request instead of starting another.

INSTANCE THEMES (0.11.64 – 0.11.67)

An instance may declare a theme: `book` or `dev`. Declaring nothing means `book`, which is exactly what instances had before — the change is backwards compatible and four older sites did not notice it.

`dev` turns the site into a technical one: a dark full-width header and footer, a monospace wordmark, sans-serif typography, an accent colour, no drop cap. The paper under the text stays light — a dark background tires the eye over a long read, and the site is still there to be read.

A trap worth recording: overriding the `--font-serif` variable inside the theme selector does NOT work, because Tailwind with `@theme inline` pastes the value straight into the generated utilities. Swapping the typeface has to go through the class itself. This only came to light in a screenshot — the post title stayed serif despite an apparently correct rule.

Two fixes followed from observation. Header icons paint themselves in ink, so they vanished against a dark background; the colour is now set once on the container and inheritance does the rest, which means anything added there in future gets the right colour on its own. And the stream disappears from the navigation while an instance has a single series — two tabs leading to the same place are noise, not navigation.

WHAT THIS LEAVES

Three of these releases repaired something that had earlier shipped too shallow: attaching reader activity, returning after sign-in, and propagation itself. Each time the first version worked under the conditions it was tested in and stopped working under the conditions it was used in.

This entry is a conclusion of the same kind. A rule saying "every release gets a changelog" is a good rule for as long as the release pace allows it to be kept. At ten releases a day it does not, and at that point you either slow the pace or change the rule — you do not pretend to be following it.