Colophon
Scaffolding post — it exists so every styled element has somewhere to be seen, and so there’s a file to copy when writing the first real one. Delete it, or keep it as a reference. Nothing depends on it.
The structure here is Jekyll’s minima theme, unchanged: a header with the wordmark and nav, a reverse-chronological list of dates and titles, and a three-column footer. The styling is the dataterminals palette — oxblood, bone, terracotta — over the same looping background the landing page uses.
Writing a post
Drop a file in _posts/ named YYYY-MM-DD-some-slug.md, with front matter:
---
layout: post
title: "The title, in quotes if it has a colon"
---
The date in the filename sets both the publication date and the URL, which
resolves to /blog/2026/08/05/some-slug/. Anything dated in the future stays
out of the build until that date passes, which makes scheduling a post a matter
of naming it correctly.
The type scale
Third-level heading
Body text runs at 1.02rem over 1.75 line-height on a 660px measure — the same width the landing page uses, which lands at roughly 70 characters a line. Long enough not to feel cramped, short enough that the eye finds the next line.
Fifth-level heading
Below the fourth level, headings stop being serif and become tracked uppercase in the faint ink, because a small serif heading reads as emphasis rather than structure.
Inline elements
Links look like this, set in terracotta with a hairline under them —
visible without hovering, since a hover-only underline disappears against a
moving background. There’s bold, italic, inline code, and
strikethrough.
A blockquote borrows the sub-tagline’s voice: serif, italic, dimmed, held off the left margin by an ember rule.
- Unordered lists
- take faint markers
- so the text leads
- Ordered lists
- number in the same ink
Code
Fenced blocks are highlighted by Rouge, in a warm palette matched to the site rather than the usual cool defaults:
def parse_manifest(path: Path) -> dict[str, Entry]:
"""Read a mod manifest and index its entries by id."""
with path.open(encoding="utf-8") as fh:
raw = json.load(fh)
entries = {}
for item in raw.get("entries", []):
entries[item["id"]] = Entry(
name=item["name"],
version=item.get("version", "0.0.0"),
requires=tuple(item.get("requires", ())),
)
return entries
Lines longer than the measure scroll inside the block instead of widening the page:
2026-08-05T14:22:09Z WARN loader entry 'tfw.workbench.compat' declares a dependency on 'tfw.core>=2.4.0' but the resolved graph pins 2.3.11 — continuing with the older version
Tables
| Field | Type | Notes |
|---|---|---|
id |
string | Unique within a manifest |
version |
semver | Defaults to 0.0.0 when absent |
requires |
list | Resolved depth-first, cycles rejected |
Images
Any image dropped in assets/ and referenced with a leading slash gets a
hairline border and rounded corners:

That relative_url filter matters — it prepends /blog, which is what keeps
links working both here and on a local preview. Bare /assets/… paths break in
one of the two.