Side project

Planchet

A design system for an app with one user, run like one with a thousand.

Company
Side project
Role
Designer and system owner; Claude Code as the engineer
Dates
October 2026 – present

Planchet is the design system behind Adjustmint, the checkbook app I am rebuilding. It is published, it is versioned, and you can open it at planchet.adjustmint.com. A planchet is the blank disc a coin is struck from, before any design is pressed into it. Planchet is the blank Adjustmint is struck from.

I built it to find out whether the way I ran a design system for a company holds up when the team is one designer and a coding agent. Most of it does. The versioning model came straight from Harbor 2.0 at The Trade Desk. It was never an experiment. It is just the right way to do this.

The Planchet home page. A sidebar on the left lists Foundations, Components, Patterns and Frameworks with every piece under each. The main column introduces the system, then four section cards reading 6 documented and 6 built as designed, 14 and 14, 13 and 9, and 4 and 4. Below them a row headed Where things stand: 37 documented, 33 built as designed, 1 built with a newer version designed, 2 designed and not built, and 1 planned.
The home page. Four sections, every piece with its version, and the changes under each one. Full size

What is in it

Foundations
6
Components
14
Patterns
13
Frameworks
4

That is thirty-seven pieces, each with a page of its own holding its specification, its drawings, its version and its list of changes.

The color foundation is primitive scales with forty semantic roles over them, and every role carries a light value and a dark one. Typography is one typeface in seventeen named styles. Nothing in the app reaches past a role or a style to a raw value, and a test fails if it does.

The spec states the floor it holds to, and it is the WCAG AA threshold rather than a house preference: 4.5:1 for every text role on the surfaces it sits on, per Contrast (Minimum), and 3:1 for the border that marks a control, per Non-text Contrast. The roles that need it carry their measured ratio next to them. A contrast claim nobody can check is a decoration.

The Color foundation page, carrying a Design 1.1.0 badge and a Built 1.1.0 badge. A specification note states that every text role passes 4.5 to 1 on its surfaces and that border-control passes 3 to 1, the WCAG AA thresholds. Four primitive scales follow, Green, Slate, Amber and Red, each running nine steps from 100 to 900 with its hex value shown. Below them a table of semantic roles, each with the primitive it resolves to in light, the one it resolves to in dark, and a description of what it is used for.
The Color foundation. Four primitive scales, then the semantic roles, each showing the primitive it resolves to in light and in dark, and what it is used for. Full size

Every piece has two version numbers

This is the part worth the rest of the page.

Each piece carries a designed version and a built version, and they are allowed to disagree. A designed version moves when the design moves. A built version moves in the commit that ships the implementation. When I have designed something that is not built yet, the site says so, in public, next to the piece.

This model came from Harbor 2.0 at The Trade Desk. The version number was design's to own, engineering built to it and tagged their builds with it, and the number together with its changelog told everybody what was actually in a build. Design was either level with the build or ahead of it, never behind. Planchet runs the same rule, and the only difference is that one person owns both numbers here, so they sit next to each other on one page instead of in a design release and a build tag.

The Versions page, open at a section headed Ahead of the code, which reads that 3 of the 36 designed pieces are ahead of what is built and 1 more is planned and not designed yet. Three cards name them: Slim entry row, designed 2.0.1 against a build at 2.0.0; Choose your categories at 1.0.0 and not built; and Loading states at 1.0.0 and not built, each with the reason and an issue number. Below the cards, a table headed Everything lists every piece with its designed version, its built version and its status.
"Ahead of the code," on the Versions page. What is decided but not yet built, stated in public rather than held in somebody's head, with the Everything table below it. Full size

One file is written by hand

`versions.json` is the only place a version number exists. The build reads it and writes everything else: the badge on each page, the list of changes under each piece, the section indexes, and the Versions page itself.

I have watched a design system carry its version numbers in several places and disagree with itself in most of them. The fix is not discipline. The fix is having one place where the number can be typed and generating every other appearance of it.

The documentation cannot quietly go stale

Two tests do the work that remembering does badly.

The screenshots have to be current. Every pattern and framework page shows screenshots of the built app, taken against a local database with made-up names and amounts, in both themes at phone and desktop widths, and committed. Retaking them is part of the commit that changes a piece's built version. A test fails when a built piece has no screenshots, or when the ones it has were taken at an older version.

The design document has to agree. The specification lives in a design document the coding agent reads, and each piece's version is written in both that document and `versions.json`. A test fails when the two disagree.

Neither test is clever. Both close a gap I have never been able to close by asking people to keep two things in step, because the thing that goes stale is never the thing somebody is looking at.

How a change gets into the system
  1. Decide the change and draw it

    Pat

  2. Raise the piece's designed version

    Pat

  3. Build it and set its built version in the same commit

    Claude Code

  4. Retake that piece's screenshots in the same commit

    Claude Code

  5. Check the versions, the screenshots and the design document against each other

    The tests

  6. Agree
  7. Mismatch
  8. Ship it, with the version stated in the summary

    Claude Code

Agree continues to step six. Mismatch returns to step two, because changing a design is mine to decide and never the agent's.

The Road to payday pattern page, carrying a Design 1.6.0 badge, a Built 1.6.0 badge and a link to its Figma page. A specification paragraph describes how the runway behaves on wide screens and on phones. Below it, a group labelled Light holds a desktop screenshot of the built app, showing the account header and then Immediate, Safe to spend with its track, and Present across the balances panel.
The Road to payday pattern page, with its Figma link and the version its screenshots were taken at. The specification first, then the built app; the page carries both themes and this is the light group. Full size

The components on the page are the real ones

The component pages do not show a drawing of a toast. They show the app's own toast, rendered from the same source the product runs on, with invented content, inside a frame so the app's styles apply in there and nowhere else on the page.

A documentation site that redraws its components has started a second implementation, and the two will part company. I have seen that happen on a system with a full team behind it. Here there was no excuse for it, because the components were already in the repository the site builds from.

The Toast component page, carrying a Design 1.0.1 badge and a Built 1.0.1 badge. At the top, the same two toasts shown once on a light background and once on a dark one. A rules list follows, giving the surface and text roles with their measured contrast ratios, an eight second fade whose timer pauses while the toast is hovered or focused, and a note that it is announced politely and never takes focus. At the bottom, under a heading reading Built 1.0.1, the live component sits with Light, Dark, Wide and Phone toggles and a toast running that reads Corner Grocery cleared, with an Undo action.
The Toast page. The specification and its rules first, including the measured contrast for every text role on it, then the live component at the bottom with its theme and width toggles and a toast actually running. Full size

Being public is a design constraint, not a publishing decision

The site is open, so the rules about what may appear on it are written into the file the coding agent reads before it does anything: no real person's name except the credit line, no account data, no keys, no internal links, no link back to the private repository.

Writing that down as a rule rather than holding it as an intention is the whole lesson of working this way. An agent will not infer that a screenshot should not contain somebody's actual grocery bill. It does exactly what is written and nothing that is not.

The accessibility rules get the same treatment. Each drawing is marked as a single image for assistive technology, with a label naming the piece and the theme, and what is inside it is hidden, because a screen reader reading out the parts of a picture of a button is worse than silence. Every page is checked in a browser on every build, in both themes, for anything that scrolls sideways on a phone and anything the security headers would block.

What I would take to a team

Generate every appearance of a number from one place. Not a convention, a build step.

Let the design and the build carry separate versions, and publish both. A system that can only describe what is already built cannot be used to plan. A system that describes what is designed and hides whether it exists is worse, because somebody will build against it.

Put the staleness check in the test suite. Documentation rots at exactly the speed nobody is looking at it. A test looks every time.

Write the rules down for a reader who will not fill in a gap. That reader was a coding agent here. At work it is a new engineer, a contractor, or me in a year. The agent is only the version of that reader who cannot pretend to have understood.