← All writing

project 17 October 2026 9 min

How I draw the figures on this site

Every drawing here is a small file run by one clock and checked by an audit that photographs it. Some of those files are templates: a seed, seeded noise and a grammar, and a different picture for every number.

The first version of this blog had a cover for every post, and they all looked alike. The shapes changed but the hand didn’t: the same low-poly blobs under the same light, one after another down the page. Nobody chose that. It’s what you get when every drawing is improvised by whoever is drawing it, and on this site that is mostly an agent.

So I stopped asking for drawings and built a way to make them. Every drawing here is now a figure: one TypeScript file, drawn on a canvas, run by a shared clock, and checked by an audit before it counts as done. Some of those files are templates. A template doesn’t draw one picture; it draws a different one for every seed you give it. The cover is the audit itself, drawn as a carousel of the stills it takes.

One file, one idea

A figure draws its subject as the thing itself. Timing closure is a logic analyser capture with the critical edge lit. A chip is a package whose layers lift apart. If an idea only makes sense with labels on boxes, it’s a diagram, and diagrams here are real text in the page (the system map on the home page is one), not pictures.

Each file declares what it is before it draws anything: an id, a title, alt text, the idea in a sentence, a style, how it moves, whether it answers the pointer, and a seed. A template declares the same, except that it writes its alt text per seed and takes its seed from the instance’s name. The audit reads those declarations and holds the drawing to them.

hairline · anatomy~4, a rocket taken apart along its axis. Each part leaves in turn, outermost first, and a leader line marks one at a time. Point at a part to pull it further out.

Seed, noise, grammar

A template is three things working together.

  1. The seed is a number. The template’s grammar turns it into every discrete choice the picture needs: which machine, which camera angle, how many layers, which way it turns. All of those choices are made once, up front, from a random stream that only the seed controls.
  2. Noise is seeded the same way, but it’s smooth. It bends a crystal’s facets, rolls a ridge field, and sets how a flow line drifts. Choices make the picture different; noise makes it alive.
  3. The grammar is the template’s rules about which choices go together. Long machines lie on their side so the explosion runs across the wide frame. A workflow’s job walks its graph and rarely turns straight back. A field seen from above is lifted harder, because height reads poorly from overhead. Without a grammar, a seed gives you a random picture. With one, every seed gives you a deliberate one.

The result is named template~seed and works anywhere a figure’s id does. The seed decides how many stations there are, where they stand, what each one is and how tall, and which are joined: one join mostly, now and then up to five. The cover of my RTL-to-GDS post is workflow~5: six stations and eight joins. The RISC-V post is workflow~11: seven stations and eight joins, laid out differently. Same file, two seeds, two drawings.

trace · workflow~11, seven stations and eight joins. One job moves through them in teal, resting where it's being worked on, while lighter work moves along every trace. Point at a station to light its traces.

There are seventeen templates so far: wireframe objects, voxel scenes, cities, districts, layer stacks, tunnels, ridge fields, low-poly solids, space (spirals, deep fields, nebulae, black holes and supernovae), endless galaxy dives, pattern cards, 3D vector diagrams, workflows, exploded machines, zoom dives, pixel fabrics and pixel still lifes. Seeds run from 0 to 999,999,999, so each template has a billion of them. The lab lists every template and lets you walk through any one seed by seed, roll a random seed, and copy the id of a drawing you like. It reads the template folder directly, so a new template shows up there without anyone editing a list.

wireframe · vector-space~3, gradient descent on a wireframe surface. Each teal step follows the slope downhill. Move across it to turn the axes.

A small vocabulary

There are nine styles: wireframe, low-poly, pixel, perspective, hairline, ink, field, trace, and three.js for the rare piece that needs a real 3D scene. Every figure and every template uses exactly one. Colour comes from the site’s tokens and nowhere else. There’s one highlight colour, teal, and it marks one thing at a time: the place to look.

The styles exist so the covers can differ on purpose. The audit refuses a cover whose date neighbour uses the same style, and it refuses any style that takes more than a third of a group. That rule is the direct fix for the first blog.

pixel · a terminal with no letters in it. You read a shell by the shape of its lines. Point at a row to invert it.

The kit underneath is small on purpose. It has a camera that projects 3D points onto the canvas, a few meshes and wire shapes, machines described as parts for exploded views, a brush that tapers like ink, a dither for pixel tone, seeded noise, and easing. Everything else is the figure’s own drawing.

Rules that are not advice

The skill that draws figures has thirteen rules. Some are about taste: the object is the explanation, one idea per figure, and the frame at rest must already say it. Most are mechanical, and a mechanical rule should be a check, not a sentence someone has to remember.

The static check reads every file and fails on these patterns where it can see them in the source, with a code and a one-line reason. It reads text, so a colour or a width computed at run time slips past it. That’s what the second half of the audit is for: a colour that slips past the text still shows up in the pixels.

ink · after LingDong-'s shan-shui-inf: ranges drawn with a tapered brush, with dry strokes under each ridge, scrolling at their own depths. Move across it to pan.

The audit takes pictures

Some things can only be checked by looking. So the second half of the audit opens every figure in a headless browser and photographs it six ways: at rest, a little later, with the pointer on it, live, at phone width, and with reduced motion on. Then it measures the pictures.

checkfails when
blank, washalmost nothing is drawn, or ink covers more than half the frame
palette, signala colour outside the tokens appears, or teal is more than a third of the ink
motiona figure that claims to move doesn’t, or a still one does
answera figure that claims to answer the pointer barely changes under it
reducedit keeps moving when the reader asked for less motion
perfa frame takes too long on average
seeda template draws nearly the same picture for different seeds

A template is audited as three instances, seeds 7, 42 and 2026, and each one must pass every check as a figure in its own right. Then their rest frames are compared with each other. The audit also lays the pictures out on one sheet per figure, and the last rule is that someone reads the sheet before calling the figure done. The numbers catch what is wrong; they don’t catch what is ugly. Half my fixes came from reading the sheet, not from the numbers.

The checks are proved too. Most have a fixture (a deliberately broken figure) or a broken case written into the self-test, which the check must catch. One fixture breaks the rules on imports, length and metadata at once. Another is a template that draws the same thing for every seed. If a change to the audit stops catching one of them, the audit is what’s broken. Three checks have no proof yet: the reduced-motion check, which guards the clock rather than any figure, and the two that check a file’s default export and its id.

wireframe · a design as a lattice of nodes, with one net traced through it hop by hop. Drag across it to turn the lattice.

What it caught

The audit started earning its keep while the first figures were being drawn, and it kept going when the templates arrived.

None of these is something a person would have caught in one look. That’s the point of a gate: it catches what nobody was going to look for.

Why bother

The drawings are made by an agent and reviewed by me, and the review is the expensive part. A gate that rejects the mechanical mistakes means that by the time I look at a sheet, the only questions left are the ones that need taste. Templates move that review up a level: I judge the grammar once, from a sheet of twelve seeds, instead of judging every drawing. That’s the same reason I put gates in front of agents at work. Done means a green check plus someone who looked, never a report that it’s fine.