Skip to main content
Everyone

Figure contract

Screenshots are the part of a manual that rots fastest. This contract exists so a stale figure is a build failure rather than something a reader discovers.

One id, one master

A figure's id is its filename stem, kebab-case and unique across the whole site:

static/img/figures/<module>/<area>/<nn>-<what-it-shows>.png
→ id: intelie-konnect/import-create/02-list-empty

Masters are 2880×1800 PNG — a 1440×900 viewport at 2× — committed to this repo and never served to a browser. Because they are byte-stable, a diff on a master means the product really changed.

The id is identical whether the shot came from the capture harness or from someone's keyboard, so a page cannot tell the difference.

Using one

<Figure
id="intelie-konnect/import-create/02-list-empty"
alt="The Import Connectors list with no connectors, showing the message No Connectors found."
caption="An empty list — the starting point."
priority
/>

alt is required and non-empty; the build throws otherwise. Write what a sighted reader would see, in a sentence. caption says why the figure is there. Add priority to the first figure on a page only — it is usually the largest thing the reader waits for.

Numbered callouts are rendered from percentage coordinates, never baked into pixels, so they stay readable to a screen reader and survive a recapture.

What happens to it at build time

npm run images turns each master into AVIF and WebP at four widths, plus a wider variant for click-to-zoom and a tiny blurred placeholder so nothing pops in white. The largest variant a browser can use is 1600px, because the text column is 800px — serving the master would waste most of its bytes.

Derivatives are generated, hashed and gitignored. The repo holds masters only.

Missing figures are visible, then fatal

A figure with no master renders a dashed Screenshot pending capture box carrying its id, so gaps are obvious in review instead of silent. STRICT_FIGURES=1 promotes that to a build failure, which is how release builds are gated.

Prefer omitting a figure to referencing one you have not captured — an unwritten page with no figures is honest; a page full of pending boxes is not.

The release gate

Two things are fine while drafting and unacceptable in public: an uncaptured figure, and a page still marked draft_stub: true. Both warn on an ordinary build and both fail under

npm run verify:release

which is npm run verify with STRICT_FIGURES=1 and STRICT_STUBS=1 set. Use it before publishing; use plain verify while writing, so a half-finished section never blocks the build you are iterating on.

Keeping them honest

CommandWhat it does
npm run figures:listScans the MDX for every referenced figure and writes the capture work list.
npm run figures:checkReports missing masters, orphaned files, dangling references and duplicate images. Always fatal.
make figures m=<module>Re-captures a module against the running local stack.
make figures-bootstrapCreates the dedicated capture workspace the harness signs in as.

The duplicate check matters more than it sounds: two figures with identical bytes almost always means a capture step silently did nothing.

Capture rules

Captures use a fixed viewport, the light theme, UK English, UTC, reduced motion and a frozen clock, and they mask generated ids and timestamps. Re-running a capture twice must produce no file changes — if it does, something non-deterministic is leaking into the image, and that is a harness bug rather than something to commit.

A handful of figures cannot be automated: third-party sign-in screens and file pickers belong to other companies. Those are captured by hand into the same path and the same contract.

Next

Steps verified on . Something wrong with this page?