Principles · how I design
Principles.
How I design, in ten sentences, each with the work where I learned it. Then the twenty-two this site is built on, checked in your browser as you read.
The ten are judgment: how I decide with a team what is worth making. The twenty-two are a floor, not a ceiling. A page can hold all twenty-two and still be ordinary; they catch what breaks, and only the judgment above them makes anything worth a look.
This page, now
22/22
principles hold, measured by the check at the foot of every page. Open it to see every value.
How I design.
Ten principles from fifteen years of products that move money, each linked to where it was earned.
- 01
Show the decision before the money moves.
Before anything leaves a person’s control, the screen says who can do what, how much, and what saying yes costs. The moment people lose trust is not the loss; it is the uncertainty after the tap.
- 02
Make the rule legible.
When the rule is the product, the interface’s job is to read the rule back to the person. At scale every unclear state becomes a support ticket, and every rule that feels unfair becomes a public argument.
- 03
Teach the idea the screen relies on.
Early products have no conventions to lean on. Each screen has to teach the idea under it: that a key on your device is the account, that an order can be signed and not yet matched.
- 04
Something to do before anything to learn.
People learn a new kind of product by using it. Give them a balance that grows, a timer, a reward to claim; the trading, the wallet and the vocabulary come after.
- 05
Price the safety action.
A protective action should never hide its own cost. Revoking an approval costs gas, so the fee is on the screen before you confirm. Safety that surprises people stops being used.
- 06
Refusal is a feature.
A system that can say no is one you can give more to. When an agent refuses, it says which rule it protected, so the person can decide whether the rule or the request was wrong.
- 07
One system, shared by everyone who makes.
A small team can cover a large surface only if everything comes from one system. With agents making the work, the system has to be closed: what exists is catalogued, and nothing is invented outside it.
- 08
Keep what people already love.
A character or a mark people already recognise is a head start that is easy to waste. Protect it from polish; build the system around it.
- 09
Ship the target in phases.
Design the whole target, then cut it into releases that each stand on their own. Nothing waits for the backend to be perfect, and nothing ships that only makes sense later.
- 10
If it can’t be checked, it isn’t a principle.
A principle comes with a measurement, a refusal and a record. Taste that lives only in one person’s head doesn’t scale to fifty makers, human or not.
This site, checked.
Twenty-two principles for this site, each a sentence a person can read and a measurement a machine can run. The measurement reads the rendered page, never the source, at five widths at build and again in your browser now.
- 01
One signal, one agent colour, states only for states
Every saturated colour on the page comes from the palette: signal orange, agent blue, and the state colours for ran, refused and asked.
Reads the computed text, fill and border colour of every visible element. Any colour with saturation above 32% must be within a small distance of a palette colour. Images and canvases are excluded.
126 of 126 page checks pass
- 02
Signal covers at most 7% of the screen
The signal colour marks the one thing that matters on a screen. Filled signal, including the hero field, stays within 7% of the visible area.
Adds the visible area of every signal fill, a third of the line boxes of signal type, and the hero field’s own coverage, which the field measures by reading back a quarter-size copy of its frame. Divides by the screen.
126 of 126 page checks pass
- 03
Signal never sets small text on paper
Orange on paper reaches only 2.7:1, so signal is used there as a fill, a rule or display type of 24 px and above, never as small text.
Finds text whose colour is signal on a background lighter than mid-grey and smaller than 24 px.
126 of 126 page checks pass
- 04
Text meets WCAG 2.2 AA contrast
Body text reaches 4.5:1 against what is behind it, large text 3:1.
Composites each text colour over the backgrounds behind it and computes the WCAG 2.2 ratio. 4.5:1 for body text, 3:1 for 24 px and up or 18.66 px bold. Text whose colour or background is in the middle of a transition is measured once it settles, as text mid-fade already was. It does not see a decorative layer painted over text; one did, on two case stages, until a review caught it.
126 of 126 page checks pass
- 05
Four faces, one family
Text is set in Söhne Breit for statements, Söhne for reading, Söhne Schmal for numbers and Söhne Mono for data.
Reads the first family in the computed font stack of every text element.
126 of 126 page checks pass
- 06
Nothing below 12 px
No text is set smaller than 12 px, and reading text is 16 px or larger.
Reads the computed font size of every text element; reading paragraphs must be 16 px or larger.
126 of 126 page checks pass
- 07
Reading lines stay under 75 characters
Paragraphs of reading text average 75 characters a line or fewer.
For paragraphs over 140 characters, counts rendered lines from their client rectangles and divides the characters by the lines.
126 of 126 page checks pass
- 08
Corners are square or round
A corner is square (2 px at most) or fully round. Nothing in between, except things that depict real objects.
Reads the computed corner radius; anything above 2 px must be at least half the element’s shorter side.
126 of 126 page checks pass
- 09
Rules are hairlines
Dividers and frames are 1 px. Controls may carry 2 px. Nothing is heavier.
Reads computed border widths on every side of every visible element.
126 of 126 page checks pass
- 10
Every control is at least 44 by 44
Buttons and standalone links give a finger at least 44 × 44 px. Links inside running text follow the text.
Measures the box of every link, button and form control that is not a link inside running text.
126 of 126 page checks pass
- 11
Images say what they show
Every image has a text alternative, or is marked as decoration because the text beside it already says it.
Checks every image for alt text, every SVG with an image role for a title, every canvas for a description or aria-hidden.
126 of 126 page checks pass
- 12
One H1, no skipped levels
Each page has one H1 and its headings descend one level at a time.
Lists every heading in order, counts H1 elements and looks for skipped levels.
126 of 126 page checks pass
- 13
Nothing scrolls sideways
At any width the page fits the screen, no text is cut off at its edge, and no figure or heading is wider than its box; only tables and diagrams scroll inside their own frame, and anything that scrolls inside its own frame draws its scrollbar in that frame’s colours or hides it on purpose.
Compares the document’s scroll width with its client width and names what sticks out, looks for any line of text that an edge cuts off, measures every figure, heading, button and cell against the box it sits in, and finds every frame that scrolls on its own and leaves its scrollbar to the system on a surface of the opposite colour.
126 of 126 page checks pass
- 14
Every figure names its source
A number presented as a fact carries a link to where it comes from.
Every element marked as a figure must have a link or a named source in its box.
126 of 126 page checks pass
- 15
Every figure has a comparison
A number presented as a fact says what it is compared with: a scale, a share, a rank, a baseline or a rate. A figure on its own makes the reader do the division.
Every element marked as a figure must carry, in its box, what it is compared with: the shared scale of a funnel, a share, a rank, a baseline or a rate.
126 of 126 page checks pass
- 16
One action, one label
Every button that goes to the same place says the same thing, so a person never wonders whether two doors lead to two rooms.
Groups every button and the nav door by where it goes, and fails when one destination has two labels. Arrows don’t count as words.
126 of 126 page checks pass
- 17
The decision comes first
On a case, the thirty-second read (the problem, what I did, what happened) starts on the first screen, before any timeline or gallery.
On a case page, finds the thirty-second read and measures where it starts against the height of the first screen, at every width.
126 of 126 page checks pass
- 18
Motion stops when you ask
With reduced motion turned on, nothing moves on its own: the field holds one frame, demos wait for you, transitions are cut.
With reduced motion on, counts running infinite animations and running scripts. Otherwise checks that reduced-motion rules exist and that every scripted motion can be stopped.
126 of 126 page checks pass
- 19
Agents can read it
The page carries structured data, links its llms.txt and agent catalogue, and offers its tools to agents through WebMCP.
Parses the structured data, looks for the agent catalogue and llms.txt links, and lists the WebMCP tools registered.
126 of 126 page checks pass
- 20
Space sits on the 8-point grid
Every padding, margin and gap is a multiple of 4 px, 8 where the space is between things; a hairline of 1 or 2 px may separate cells.
Reads the computed padding, margin and gap on every side of every visible box outside the product prototypes. Each value must be a multiple of 4 px; values under 3 px pass as hairlines. The build already rounds every size in the stylesheets and inline styles to the grid, so the check measures whether the browser agrees.
126 of 126 page checks pass
- 21
Type keeps the rhythm
Every font size is an even number of pixels and every line height a multiple of 4, so lines across columns share a baseline.
Reads the computed font size and line height of every text box. Sizes must be even pixels and line heights multiples of 4 px, which is what lets two columns of different type share a baseline. Fluid sizes are rounded at build with CSS round().
126 of 126 page checks pass
- 22
Quotes curl, dots are one dot
Reading text uses typographer’s quotes and apostrophes, one ellipsis character, a real minus and a real multiplication sign; code keeps its own.
Walks every run of reading text outside code and the prototypes and looks for a straight quote or apostrophe, three dots in a row, or a hyphen standing in for a minus before a figure. The build converts them; the check catches what arrives another way.
126 of 126 page checks pass
Every page, three widths.
The check ran in a headless browser on every page of this build at a phone, a tablet, a laptop and two desktop widths.
| Page | 390 px | 768 px | 1280 px | 1536 px | 1920 px |
|---|---|---|---|---|---|
| / | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /cv | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /now | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /patterns | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /press | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /principles | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work-with-me | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/blum | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/de-fi | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/deed | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/deed-design-system | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/dogs | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/factory | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/hyperlens | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/more | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/trust-wallet | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /work/waves | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /writing | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /writing/ask-before-you-spend | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
| /writing/principles-that-run | 22/22 | 22/22 | 22/22 | 22/22 | 22/22 |
Palette.
Two grounds, one signal, one colour for agents, and state colours that only ever mean a state. Contrast is computed, not guessed.
Four faces, one family.
Söhne by Klim Type Foundry, licensed for this site and subset to the characters it uses. Each face has one job.
Aa 0123 Ask
Söhne Breit · Statements
Headlines and claims. Wide, heavy, close.
Aa 0123 Ask
Söhne · Reading and signs
Body text, labels, buttons.
Aa 0123 Ask
Söhne Schmal · Numbers
Figures, counts, version numbers.
Aa 0123 Ask
Söhne Mono · Data
Measurements, labels, hashes, code.
Identity.
Four marks carry the identity, and nothing else is decorated.
The wordmark
Söhne Breit, close-set, with one orange e. At the foot of every page it is drawn as a field of pixels that settles while you read: the same word, as a machine sees it.
The sign
A short orange rule before a kicker. It marks the one thing on a screen that matters most, and it appears once.
The covers
Every piece of writing gets a cover from one series: a number in Schmal, one object drawn in the wordmark’s grain, on paper. The series is drawn at build; a new piece gets a number and an object.
The pixel objects
Drawn things are drawn as pixels on a square grid, ink on paper, at most one cell orange. Photographs and screens are shown as they are. Nothing is illustrated in a second style.
Grid and rhythm.
Space sits on an 8-point grid, with 4 as the tight step and 1 or 2 px for hairlines. Type sizes are even pixels; line heights are multiples of 4, so columns of different type share a baseline. Reading lines stay under 75 characters. The build enforces all of it: a pass over every stylesheet and inline style rounds each size to the grid, fluid sizes with CSS round(), and the checks above measure whether the browser agrees.
Space
4 · 8 · 16 · 24 · 32 · 48 · 64 · 96
Type
1214161820243248
size / line: 12/16 · 14/20 · 16/24 · 18/28 · 20/28 · 24/32 · 32/36 · 48/48
Layouts written since version 7 are phone first and grow at 760, 900, 1000, 1100 and 1200 px; the first stylesheet still narrows from the desktop down, and both are measured at five widths. Tiles and cards respond to their container, not the screen. On a phone a table drops its secondary columns or scrolls inside its own frame rather than shrinking its type, controls stay 44 px, and the fixed bar respects the safe area.
Motion.
Three motions, each with a reason, and none when you ask for less.
- The reveal. Blocks arrive in reading order: opacity and a 26 px rise over about a second, the second and third block a beat later. It never moves anything you are already reading.
- The grain. The wordmark field and the cover objects settle pixel by pixel, in steps, not in fades. It is the identity moving, not an effect on top of it.
- The curtain. The footer waits under the page and is uncovered as the page ends, so the last scene is already in place. On a phone it simply follows.
Prototype players stop when you take over. With prefers-reduced-motion set, every one of these is off and the check at the foot of the page counts anything still running.
Voice.
Words follow the same principles. Plain, short, present tense; the subject is what a person can do.
Uses
- principlea rule a person wrote and a machine checks
- recordwhat happened, readable afterwards
- refusea system that can say no
- askthe agent stops and checks with a person
- Ithe work is owned by name
- peoplethe ones using the product
- plain figures with a sourceevery number can be checked
- in developmentstatus stated as it is
- with agentshow the work was made, disclosed
- fixed scopewhat is made, agreed before starting
- builddesign that ships as working code
- whyevery refusal names its reason
Refuses
- revolutionaryhype that nothing can prove
- seamlesshides the seams that matter
- AI-poweredsays nothing about what it does
- guaranteenothing can enforce it
- frictionlessfriction protects people’s money
- unlockmarketing filler
- leveragejargon in place of a verb
- best-in-classa ranking without a source
- game-changinghype that nothing can prove
- honestlycandour shows in the work itself
- trust usreceipts instead of reassurance
- autonomous (unsupervised)someone always holds the rules
Exceptions.
The only places a principle does not apply, each with its reason, marked in the page itself so the check skips them on purpose.
- The wordmark in the top bar: its e stays signal on paper. It is a logotype, which WCAG 1.4.3 exempts from contrast, and it is never used for reading text.
- Each case’s stage, plates and tile: the client’s brand in its own colours, because the work should be seen in the world it was made for. The palette principle skips them; every other one still applies.
- Every phone that frames a screen: rounded corners, because it depicts a physical device.
- Palette swatches on this page: signal fills larger than the budget allows in one place, because they show the colour itself.
- The brand demonstration with the principles turned off: no exception. It breaks them on purpose, and the check reports it.
Measured at build.
Measured on the built site in a lab, Lighthouse 13.5.0 with its default throttling, on 2026-10-25. Each row is the median of three runs; every run, every check and every axe result is in proof.json. axe-core: 0 violations across 21 pages at 390 and 1280 px · HTML validation: 0 errors, 0 warnings in 22 files · the check: 126 of 126 page checks hold every principle at the top, middle and end of each page, at five widths and with reduced motion
| Page | Form | Perf. | Access. | Practice | SEO | Agents | LCP | CLS | TBT |
|---|---|---|---|---|---|---|---|---|---|
| / | mobile | 91 | 100 | 100 | 100 | 100 | 3.1 s | 0 | 60 ms |
| / | desktop | 94 | 100 | 100 | 100 | 100 | 0.8 s | 0.009 | 180 ms |
| /principles | mobile | 92 | 100 | 100 | 100 | 100 | 2.7 s | 0.001 | 140 ms |
| /principles | desktop | 99 | 100 | 100 | 100 | 100 | 0.7 s | 0.01 | 110 ms |
| /work-with-me | mobile | 96 | 100 | 100 | 100 | 100 | 2.6 s | 0 | 10 ms |
| /work-with-me | desktop | 98 | 100 | 100 | 100 | 100 | 0.6 s | 0.009 | 120 ms |
| /work | mobile | 95 | 100 | 100 | 100 | 100 | 2.9 s | 0 | 10 ms |
| /work | desktop | 100 | 100 | 100 | 100 | 100 | 0.6 s | 0.009 | 10 ms |
| /work/blum | mobile | 92 | 100 | 100 | 100 | 100 | 3.2 s | 0 | 90 ms |
| /work/blum | desktop | 96 | 100 | 100 | 100 | 100 | 0.8 s | 0.009 | 150 ms |
| /work/deed-design-system | mobile | 92 | 100 | 100 | 100 | 100 | 3.0 s | 0 | 30 ms |
| /work/deed-design-system | desktop | 96 | 100 | 100 | 100 | 100 | 0.7 s | 0.009 | 170 ms |
| /work/deed | mobile | 93 | 100 | 100 | 100 | 100 | 3.1 s | 0 | 10 ms |
| /work/deed | desktop | 97 | 100 | 100 | 100 | 100 | 0.7 s | 0.009 | 130 ms |
| /work/dogs | mobile | 95 | 100 | 100 | 100 | 100 | 2.9 s | 0 | 30 ms |
| /work/dogs | desktop | 99 | 100 | 100 | 100 | 100 | 0.8 s | 0.009 | 100 ms |
| /work/factory | mobile | 96 | 100 | 100 | 100 | 100 | 2.6 s | 0 | 0 ms |
| /work/factory | desktop | 100 | 100 | 100 | 100 | 100 | 0.6 s | 0 | 10 ms |
| /work/trust-wallet | mobile | 91 | 100 | 100 | 100 | 100 | 3.4 s | 0 | 10 ms |
| /work/trust-wallet | desktop | 99 | 100 | 100 | 100 | 100 | 0.8 s | 0.009 | 90 ms |
| /work/waves | mobile | 94 | 100 | 100 | 100 | 100 | 2.9 s | 0 | 30 ms |
| /work/waves | desktop | 97 | 100 | 100 | 100 | 100 | 0.7 s | 0.009 | 140 ms |
| /writing/principles-that-run | mobile | 92 | 100 | 100 | 100 | 100 | 2.9 s | 0 | 100 ms |
| /writing/principles-that-run | desktop | 97 | 100 | 100 | 100 | 100 | 0.7 s | 0.009 | 140 ms |
For agents.
The principles are written for people and published for machines. An agent can read them, follow them and check its own work against them.
- principles.json: palette, faces, principles and voice as data.
- principles.md: the same principles as an agent skill, listed in the site’s agent catalogue.
- WebMCP tools on every page, for browsers that support them: run_design_critic, get_design_principles, list_work and start_a_brief.
- brief.md and brief.json: how an agent briefs me on a project for the person it works for.
- llms.txt: the site in one page of Markdown.
Changes.
- 9.2
25 October 2026
Three checks join the nineteen, and they measure craft rather than hygiene: space sits on the 8-point grid, type keeps a 2-px size scale with line heights on 4 px, and reading text uses typographer’s punctuation. They hold because the build now enforces them: a pass over every stylesheet and inline style rounds each size to the grid, and a pass over the copy curls the quotes. Also new: one footer across the site, with the Paris time, the address, and plain links that ask an AI about this site; one header for every essay, with a contents list built from its headings; and a numbered cover series for the writing, drawn at build in the wordmark’s dither.
- 9.1
25 October 2026
The nineteen checks stay nineteen; the fit check measures more. Anything that scrolls inside its own frame now draws its scrollbar in that frame’s colours or hides it on purpose. The De.Fi prototypes showed black system scrollbars down their white screens on machines that always show scrollbars, because this dark site’s colour scheme reached inside them. No screenshot caught it: the headless browser that takes them hides scrollbars, so the check now measures what the eye there could not see.
- 9
24 October 2026
Three checks join the sixteen, and they measure understanding rather than hygiene: every figure has a comparison, one action has one label, and on a case the decision comes first. Two cases join the work: DEED’s factory, and the DEED design system, read as a case study.
- 8.1
23 October 2026
The sixteen checks are unchanged. The page now opens with the ten principles I design by, each linked to the work where it was earned. The fit check also measures every figure, heading, button and cell against its own box, after a figure on the home page outgrew its column at 1,470 px. New on the site, each held to the same sixteen: prototype players that play a case’s real screens and stop when you take over or ask for less motion, a year strip that places each project in its time, and a film on the home page with a pause button.
- 8
23 October 2026
The vocabulary changed, not the measurements. What this site called a law is now what it is: sixteen design principles, each with a check, and every page is measured against them as before. One check measures more: the fit principle also finds text cut off at the edge of the screen. Two exceptions recorded: each case opens in its client’s own colours, inside its stage, plates and tile; and the wordmark’s orange e, a logotype. Cut: a footer colophon, a sound toggle, measurement overlays on the headline, and copy that described the site instead of the work. The cases were rebuilt on one template. Fixed: on two case stages a decorative glow painted over the meta line, down to 1.6:1, which the contrast check cannot see; the glow now sits under the text, and the check says so.
- 7
22 October 2026
The principles run live: a check in the browser on every page, and the same check at build on every page at 390, 768 and 1280 px. The hero field keeps inside the signal budget by measuring its own frame. The signal bar behind the headline went, because it covered about 11% of a desktop screen; signal type below 24 px is banned from paper, because it reaches 2.7:1; fonts are subset to the characters in use, from 358 KB to 173 KB; the principles are published as data and as an agent skill, and the site offers its tools to agents through WebMCP.
- 4–6
October 2026
The signage system these principles grew from: ink and paper, one signal colour, Söhne by role, cases from the original working files with every figure sourced, the treasury instrument from DEED, the press kit, and pages that read without JavaScript.