tade — every picture on this site is drawn by the program

blog /

Every picture on this site is drawn by the program

A screenshot starts going out of date the day after it is taken. Every screen in a post here is rendered by Tade itself, from the scenarios its own tests protect.

The Tade project·2 min read·screenshow-this-is-built

A screenshot is a photograph of a program on one afternoon. It is right until somebody moves a column, and then it is wrong in a way nothing fails over: the picture still loads, the page still looks finished, and the only person who finds out is the reader who installs the thing and cannot find what they were shown.

So there are no screenshots here. Every screen on this site — the front page and every post — is rendered by Tade, from the same scenarios its golden tests protect, and committed as text.

watching-an-agentdrawn by Tade
The window: agents down the left with what each has cost, the one being watched in the middle, the orchestrator along the bottom. Real text, not a picture — try selecting a line of it.

What you are actually looking at

Not an image. That block is HTML: one element per row, one per run of colour, with every run pinned to the number of columns Tade drew it in. The colours come out of Tade’s own palette file, and the font is Iosevka Term cut down to the 189 code points the screens actually contain.

Which has three consequences worth the trouble:

  • It is text. You can select it, search it, and read it with a screen reader. So can a crawler, and so can a model.
  • It cannot drift. A synced screen is a file in the repository. When the window changes, the file changes, and the change arrives as a diff somebody reviews.
  • It cannot tear. Every run carries its own column count, so a glyph the font has not got can never shift the rest of the row.

Where they come from

One script asks Tade to draw itself:

TADE_REPO=~/tade npm run sync:screens

It imports Tade’s draw(state, frame) — a pure function of a state and a frame, which is the whole reason this is possible — and renders each scenario at 120, 96, 72 and 56 columns. A phone gets the window Tade would draw on a narrow terminal, not a wide one shrunk to five-pixel type.

The output is committed, so the deploy needs no Tade checkout at all. And a scenario that disappears from Tade does not quietly vanish from the site:

$ npm run sync:screens
✗ a-schedule: no such scenario in this Tade

That is the point of the whole arrangement. The failure is loud and it happens on somebody’s machine, rather than silently on a page a thousand people read.

In a post

A post is a markdown file. Naming a screen in it is one fence:

spend · paneldrawn by Tade
The spend table, cropped to the panel. A quoted price and an estimate are never added together, and a subscription is never totalled as dollars.

The fence says which screen and which rectangle of it; the build draws it. Rename nothing, export nothing, remember nothing — when sync:screens next runs, every post that names that screen is right again.

A picture nobody can regenerate is a claim nobody can check.

What this does not fix

It does not make the screens interesting, and it does not stop a post from describing something the screen does not show. Nothing here reads the prose. The pictures are honest about the window; the words are still somebody’s job.

If you would rather see the window than read about it, it is on the front page, and one command away:

npm i -g tade-sh
blog← oldernewer →The Tade project│2026-09-28│2 min│top