PRESTON · THE DESIGN SYSTEM

One face, and the two layers it comes in.

Every value on this page was measured off the element beside it, after paint, from this document. Nothing here is retyped from the token file — so if a token changes, the page changes, and if the app stops reading a token, the page stops showing a value rather than printing the one it remembered.

Preston draws with one mark, one type ladder, one palette and one rhythm, on every surface without exception. On the surfaces that show understanding it draws with a second vocabulary on top, where each choice carries a fact. Those are two different promises, and the second is the one that gets copied where it does not belong.

the part a reader gets wrong

Coherence is not sameness. The climb and the review pages work because their visual choices carry meaning: colour encodes kind, fill encodes standing, a slash means no-longer-stands, №n means ordinal position in a real sequence. Copy that onto a pricing page and the meaning becomes decoration — and afterwards nobody can tell which choices are load-bearing. That is the usual way a design system dies.

LAYER ONE · THE FOUNDATION

Universal. No exceptions.

the mark · the type ladder · the palette · the rhythm · the voice

Marketing, auth, docs, the desk, admin, legal, error states, empty states. Nothing about persuasion requires a different diamond, and nothing about a login form requires losing the header.

LAYER TWO · THE SEMANTIC GRAMMAR

Only where there is understanding to encode.

kind colour · the shape axis · standing fill · the slash · ordinals · lenses · receipts

A settings form has no kinds and no standings. Applying this there is the same category error as the drift it was meant to fix, pointed the other way.

The sanctioned exceptions

Three, named here so they read as decisions rather than as drift. There is no fourth, and a fourth would be written down in the token file before it was drawn.

text-heading and text-display sit above every witness role and are the whole licence. A 19px landing headline is not coherent, it is mute. They never appear on a surface that shows understanding.
The witness ladder is a scanning rhythm for one-sentence claims. Multi-paragraph clauses set at 14.5px would be measurably harder to read, and legal text is the one place a reader is presumed to have read it. Legal converts its mark, eyebrow, radii and badges only.
components/ui renders a claim axis, and a claim has no standing to encode as fill. Forcing the ring there would draw a fact that does not exist. Only its chip metrics and its openable-line treatment unify.

every surface, no exceptions

The mark

One component draws it, and it is the only way a wordmark reaches a page. There were three, and a visitor could meet all of them in two clicks. The diamond is --kind-promise and the wordmark is --ink: both are theme tokens, so the mark inverts with the app and there is no second asset and no dark logo.

public

Preston

signed in

Preston

with a lockup

Preston· invite-only beta

the glyph alone, by kind

The favicon is the same diamond. It cannot read a CSS variable, so design-system.test.ts asserts its two fills are literally the two --kind-promise values — a copied colour with nothing checking it is how a fourth mark gets born.

The type ladder

Sixteen roles and two sanctioned exceptions, named by the job each one does. The rule for choosing is to ask what the text IS, never how big it should be — and if no role fits, the honest move is to add one to preston-tokens.css with a reason. This is the ladder the face was proved on; until it had names it was ten pixel sizes stamped ~714 times, which is not a system but twenty-one files behaving well. The third column is what each specimen actually renders at, so a role that declares no leading of its own reports the one it inherits — the line under each role name is the exact set of properties that role declares.

--type-meta

2h ago

the trailing stamp: a time, an arrow, a count

the right edge of every stream row

--type-slug --type-slug-track

riosgabriel/relay

an identity string, read for recognition rather than for meaning

repository names, keys, run identifiers

--type-section-label --type-section-label-track

names a section or a field inside a surface

SectionRule, the docs' second rail, every form label

--type-byline

the row's naming line — the ordinal, the change word, the standing

every event in the stream

--type-kind-label --type-kind-label-track

TENSION

a kind's own name — never rendered without the kind's hue beside it

the stream, the standards page

--type-page-eyebrow --type-page-eyebrow-track

PRESTON · THE DESIGN SYSTEM

names the surface you are on

the top of every page in the app

--type-ground --type-ground-leading

outbox discipline → idempotent replay

running mono content: receipt paths, ledger lines, lens rows, ticks

the receipt strip, the lens row, the lifecycle ticks

--type-control

Point your agents at this

a control's label

every button and every door in the app

--type-code --type-code-leading

return withIdleAndWallTimeout(run, budget);

a line of code AND the gutter that numbers it — one leading, so they finally align

diff excerpts, the climb's phase rail

--type-mark

PRESTON

the product signing its name

preston-mark.tsx, and nowhere else

--type-inline-code

A read that starts at package.json and goes down from there.

code set inside a sentence — the one role measured relatively, because its job is to be a little smaller than whatever it interrupts

every backticked span Preston writes

--type-gloss --type-gloss-leading

held loosely — could change as the read deepens

the explaining line beneath a claim

the inspector's standing section, every card's second line

--type-claim --type-claim-leading

Ledger, outbox and bounded retries compose into one delivery guarantee.

the sentence a unit exists to carry

every event row, every claim node

--type-reading --type-reading-leading

A passage read in paragraphs rather than scanned in rows — looser leading, a longer measure, and the one place a reader is presumed to have read every word.

a passage read in paragraphs

the docs, the legal pages

--type-title --type-title-leading

What Preston won’t say

a surface's own title

card headings, panel titles

--type-lede --type-lede-leading

Preston has never read this repository.

the one sentence a surface is built around — and the top of the non-persuasion ladder

the climb hero, and the one empty state

PERSUASION ONLY

--type-heading --type-heading-leading --type-heading-track

One face, two layers

PERSUASION ONLY — a marketing, legal, auth or admin page's own title

the legal pages, the sign-in page

PERSUASION ONLY

--type-display --type-display-leading --type-display-track

An engineer who reads first

PERSUASION ONLY — the landing hero, and a docs page's h1

the landing, the docs page headers

Tracking

One ladder, and its steps are semantic rather than decorative: the wider the tracking, the further out the label stands from the content it names. Most roles bake their own step; these five are for when a role's size is right and its tracking is not.

names the whole surface
names a section within it
an identity read for recognition
a label sitting in the row it names
the tightest step — a label inside its own control

The palette — neutrals

Neutrals carry no meaning of their own. They say how far forward a surface sits and nothing else, which is exactly why a neutral may be used anywhere and a kind colour may not.

the page itself — the ground every surface sits on

a navigation rail, standing beside the content rather than under it

the line where a rail stops and the content begins

a surface lifted off the page — a card, a panel holding one claim

a quieter surface than a card: the docs rail, the desk sidebar

the ground under code — a diff, an excerpt, an evidence chip

the ordinary hairline: a section rule, the border around a card

a hairline INSIDE a surface, quieter than the one around it

the divider between two rows of one list

a row under the pointer, and the row that is currently selected

a dashed or provisional edge — a boundary not yet settled

the backdrop under a sheet or an inspector — the page pushed back, so the sheet is what is being read

The ink ramp

Six steps, and the step is the meaning: how dark a piece of text is says how much of the reader's attention it is asking for. Each line below is printed in the ink it describes.

the sentence a surface exists to carry
ordinary prose — the document's own default
supporting text: a gloss, a control that is not the point
a label naming something else on the screen
a stamp: a time, an ordinal, a count
the one warm ink — names the surface you are on, and marks the active lens

The kind families

Colour marks consequence — what it costs to be wrong about this — and never where the claim came from. Each family is a triad: an accent for the label, a tint for the body, a hairline that sits on the tint. lib/kinds.ts is the only place a kind becomes these classes.

RISKrisk · principle

it bites. The one flag, and rationed — red is the colour a reader must not learn to skip.

--kind-risk
--kind-risk-surface
--kind-risk-border
TENSIONtension · convention · gap · concern · question

unresolved. Something missing, something in disagreement, or a rule observed rather than decreed.

--kind-tension
--kind-tension-surface
--kind-tension-border
OWNEDsource · pattern · reading

seen and held — a discipline recognized in the code, a leaf of evidence, a thing that can be acted on.

--kind-owned
--kind-owned-surface
--kind-owned-border
PROMISEbelief · discipline · connection · grounding

a relation drawn between two things already on the record. The mark is this colour.

--kind-promise
--kind-promise-surface
--kind-promise-border
DECISIONdecision · orientation · composition · subject

a synthesizing read that names a centre — an orientation, a composition, a decision quoted verbatim.

--kind-decision
--kind-decision-surface
--kind-decision-border

the ink that goes on the owned fill — the primary door's own foreground. Every other text colour comes off the ink ramp and inverts with the theme; this one has to stay legible on a fill that does not, which is why it is a token and not a judgment call at the call site.

Context origins

Provenance, not kind. Where an instruction came from is a different question from what it costs to be wrong about it, so it is a different axis with its own hues — deliberately outside the kind namespace, so a CODE origin is never mistaken for a source claim.

PRESTONPreston's own read of the repository said so
TEAMa person on the team said so, and Preston kept it
CODEthe code itself says so — the claim is checkable without asking anyone

Edges

Relationship temperature, independent of the two nodes an edge links. A because-of edge is teal whether it runs between two risks or two decisions: the colour belongs to the relation, not to its ends.

because of — this rests on that
contradicts — the two cannot both stand
weight ↑ — this makes that matter more

Shape and elevation

Two radii, and only two. Ten shipped before this — four of them a second parallel ladder — which is how a panel and the chip inside it ended up rounded four different ways on one screen.

a control or a tag — something you press or read as one unit

a surface — something that holds other things

not a third step: the corner softening on a 10px diamond, and only preston-mark.tsx may read it

a panel that has come forward — an inspector, a sheet

a card resting on the page

Measure

Four widths, named by what goes inside them. Ten shipped before this. The bars below are the real containers; the reading is what each resolves to right now, which is why the last one is a character count and not a number anybody chose.

--measure-shell

the page's outer bound

--measure-read

the reading column — a hero, a claim, a paragraph of the record

--measure-note

a short standalone block that should not run the full column

--measure-passage

continuous prose, bounded in characters rather than pixels, because a reading measure is a character count

The two families

Two, and there is no third. If the eye should verify it, it is mono.

Preston reads it firstwhat a human reads
Preston reads it firstanything the eye should verify — a label, a kind, a path, a line of code

The rhythm

The one part of the foundation with no role names. It rides Tailwind's 4px step, half-steps allowed, and the six intervals below are the ones the app actually uses. Saying that plainly is better than implying a naming that does not exist — and this row is where the next set of names will come from.

a claim to the gloss beneath it
one row to the next in a stream
between items on one line — a byline's chips
one block to the next inside a surface
between sections
the page's own top and bottom

The doors

Three tiers and one geometry. The primary is teal because a button is an ACT and teal is owned — blue is the mark. Five primaries shipped before this in four different foregrounds, which is the tell: nobody chose blue-on-something, each site chose a light colour locally and moved on.

One deviation from the witness row’s geometry, written down rather than drifted into: min-h-11. The row’s px-4 py-2 around an 11px label is about 32px tall, which is under the touch target — fine on a desk surface reached with a mouse, not fine on the two buttons that carry every signup on a phone.

The one empty state

One component, one shape, and the only form an error, a refusal or an empty list takes anywhere in the app. There were seven, from 13px to 38px, and two of them wrapped themselves in a bordered card so the same sentence was furniture on one route and a hero on another.

never read

Preston has never read this repository.

Back to the docs

Three parts and no fourth: a label naming the situation, one sentence, and at most one way onward. No kind colour, no standing, no ordinal — a session that expired is not a claim, and dressing it as one is the category error above, pointed the other way.

only where there is understanding to encode

Three axes, three jobs. Colour marks consequence, shape marks kind, and fill with the slash marks standing. Only the first of them disappears for a colour-blind reader, which is the whole reason the second exists.

Kind, said twice

The shape axis is not invented here. /u/:owner/:repo/standards shipped four of these for exactly this reason, and converting that page onto the standard would have deleted a working colour-blind-safe encoding in the name of coherence. Promoting it instead makes the standard better rather than merely more widespread. All five glyphs come from one Unicode block.

RISKit bites. The one flag, and rationed — red is the colour a reader must not learn to skip.
TENSIONunresolved. Something missing, something in disagreement, or a rule observed rather than decreed.
OWNEDseen and held — a discipline recognized in the code, a leaf of evidence, a thing that can be acted on.
PROMISEa relation drawn between two things already on the record. The mark is this colour.
DECISIONa synthesizing read that names a centre — an orientation, a composition, a decision quoted verbatim.

The hollow variants (◇ ○ □) are deliberately unused: fill is already spoken for by standing, and a shape axis that borrowed it would say two things with one mark. decision’s ▾ is one of the two shapes this adds — a promise ▸ points forward at what it will keep, a decision ▾ comes down.

The circle is the other. owned used to be ●, and then the ring below became the app’s state mark — whose solid form is a filled circle meaning earned. One shape, two vocabularies: an evidence chip read ● BECAUSE OF a scroll away from a relay teaching that ● is what a ratified judgment looks like. The circle belongs to state, so the kind axis gave it up. ▮ is the quotation bar — a source is what a claim rests on — and it is the shape furthest from ▸, which matters because promise-blue against owned-teal is exactly the pair a deuteranope flattens.

Standing, and the stream

The ring in every state it has, drawn by the component the climb and the review pages use. Hollow means not yet earned, solid means earned, the inner red dot means two live readings disagree, and the slash means no longer stands — kept on the record, no longer binding the read.

lens
visit 1 opened · 24 files read2h ago
ORIENTATION2h ago
Relay is a delivery system: everything it accepts is written down before it is sent.
PATTERN2h ago
Every outbound job passes through outbox.enqueue before the transport sees it.
src/outbox/enqueue.ts:41
GAP1h ago
Two readings disagree about whether replay() is idempotent under a partial flush.
CONNECTION58m ago
The ledger and the outbox are one delivery guarantee, not two mechanisms.
rests on №2
READING41m ago
The retry budget is unbounded.

Row 2 carries a code span because authored() handed the renderer a sentence with backticks in it, not because this page styled one. Preston’s backend injects those ticks deterministically after every prose pass, so a surface that prints his sentence raw prints backticks at the reader — which is why the slot is typed and a plain string does not satisfy it.

№n is display-derived: the caller’s own 1-based position in the list it is showing, never a stored identity. Two readers looking at different slices see different numbers for the same event, and that is correct.

The standing vocabulary

One map, rendered from the function that owns it — so the words on this page cannot disagree with the words on the climb.

held loosely
held loosely — could change as the read deepens
stands
independent support attached — direct, but revisable
ratified
confirmed by the team, not only by Preston's own read
contested — two live readings, neither chosen
two live readings disagree — neither chosen yet
no longer stands
withdrawn — kept on the record, no longer binds the read

Lenses

Selecting a lens never reloads a list — it dims. Three tiers, from one function: a match stays at full opacity, the thing a match rests on drops to 0.55, everything else to 0.16. A reader can still see what was filtered out and what it sat next to, which a list that removed rows could not show.

The row above is live: choose held, open or withdrawn and the stream dims around it. The counts come from the events themselves — a lens that carried a number nothing produced would be the one thing a receipt must never do.

Receipts

How an understanding formed: the counts, and the load-bearing path through the claims that produced it. Rendered straight off the receipt the server composed and never counted a second time — a surface that re-derives a number is a surface that can disagree with the record it is showing.

HOW THIS UNDERSTANDING FORMED
  1. everything accepted is written down
  2. outbox.enqueue before the transport
  3. ledger and outbox are one
  4. the delivery guarantee

The counts above are composed from the five events in the stream, once, at the seam — which is the same thing the server does before this component ever sees them.

two ways to be wrong, both fail a build

A style sweep buys three months; the mechanism is what lasts. There are three parts, and this page is the third.

  1. One component draws the mark.A fourth brand cannot be introduced by hand, because there is no hand-drawing path left.
  2. The gate refuses a value spelled anywhere else.design-system.test.ts fails the build on a colour literal, a font-family, or a bracket size, tracking or radius class outside preston-tokens.css. The debt table that let the app get here is now empty, so the rule is simply the rule: not one, anywhere.
  3. This page is measured, and its list is gated.Every value here is read off the element beside it after paint, so it cannot drift. system-catalog.test.ts holds the catalog equal to the token file in both directions — a token added without a meaning fails, and a meaning whose token was deleted fails too. A system page that could describe a system the app no longer has is worse than no system page.