Writing in blocks
This blog has no rich text editor and no markdown. Posts are typed arrays of blocks, and the constraint is doing real work.
Every post on this site is an array of typed blocks. There are ten of them, the list is closed, and adding an eleventh has to be argued for.
The usual approach is markdown, which is a fine authoring format and a poor design system. Markdown lets me write six heading levels, arbitrary nesting, and an inline <div> when I get impatient. Every one of those is a way for a post to invent its own typography and quietly break the scale everywhere else.
So the content model is a discriminated union, and an invalid post is a type error rather than a page that renders slightly wrong in production.
export type Block =
| { kind: "heading"; text: string }
| { kind: "subheading"; text: string }
| { kind: "paragraph"; content: Inline[] }
| { kind: "lede"; content: Inline[] }
| { kind: "list"; ordered?: boolean; items: Inline[][] }
| { kind: "code"; language: string; code: string; caption?: string }
| { kind: "terminal"; lines: TerminalLine[]; caption?: string }
| { kind: "callout"; tone: "note" | "warn"; title?: string; content: Inline[] }
| { kind: "table"; head: string[]; rows: string[][] }
| { kind: "divider" };Three rules that do the most work
Rhythm belongs to the container
Blocks carry no outer margin. A single > * + * rule on the prose container owns all vertical spacing, so the gap between a paragraph and a table is the same as between two paragraphs, forever. The only exceptions are relationships — a heading and the text beneath it tighten up, because they're one unit.
The measure is applied to text, not the container
Prose caps at 68 characters. The obvious implementation — cap the container — is wrong, because it clamps children too, and then a table can never reach full width without negative-margin escapes that break the moment the gutter changes. So the cap lives on the leaf text elements, and wide blocks simply don't inherit one.
Inline emphasis doesn't nest
A strong can't contain a link. This sounds restrictive and almost never is: when I reach for nested emphasis, the honest fix is that the sentence is doing too much and wants to be two sentences.
The one that changed the writing
The lede block is capped at one per section. It renders larger than body text, so it's the sentence a skimmer reads. Having exactly one slot forces the question what is the single most important sentence here — and often reveals that a section has two arguments in it and should be two sections.
The full spec, with each block rendered next to the rule governing it, is on the guidelines page.