Case Study

Designsystemsdon'tsurviveanAIbuildpartner.

Lune · DSYS: Brand Foundation & Design System

Models drift, invent tokens and lose the brand between sessions. DSYS is fifteen markdown files and a pre-commit hook that keep a language model on-brand. A full visual iteration that changed no component code proved it.

Project

Lune · Wedding Planning App

Role

Product Designer · Design System Lead

Stack

Claude · Cursor · Figma MCP · Tailwind

Year

2026

The Lune design-system showcase, running the real components with a live theme toggle

Impact at a glance

The system in numbers.

15 files

Markdown written for a language model to parse. One concern per file.

1 pre-commit hook

Checks colour, type, spacing and components against the token list on every staged change. Nothing pushes until it passes.

0 components rebuilt

A new palette, ink and AI signal shipped as changes to token values.

The Problem

An LLM starts every session with no memory of your brand.

Working with Claude and Cursor as build partners exposed a failure no design system I'd used was built for. Ask for a card at 9am and you get the documented one. Ask at 4pm in a fresh context and you get a hex value that appears nowhere else in the codebase.

Storybook doesn't fix this. It's a rendered artifact behind a build step, made for people browsing components. The model needs each decision written as text, with its constraints attached.

Context

At Komodo, changing a token took a ticket.

Komodo Health's Fire design system was mature and well built, in Storybook, with documentation owned by engineering. I couldn't change any of it myself. That works for a large org. It can't work on a two-week sprint with one engineer.

Komodo · Fire design system

Days or weeks

File a ticket
Engineer updates the Storybook source
Review in staging
Merge

Docs were MDX that engineering deployed. Figma and Storybook could disagree for weeks.

Lune · DSYS

Minutes, alone, no handoff

Edit the value in the token file
Every surface that references it moves

The spec file is both the documentation and the build partner's briefing.

Step 01

The brand came first, in one day.

I gave Claude the positioning and asked it to attack the assumptions. Where does “warm” tip into sentimental? Where does “intelligent” read as cold? Several of my first instincts didn't survive.

Every line in the brief had to name the token it produced. Fraunces for display, DM Sans for UI, espresso ink, one accent, and one colour kept for AI and availability. A token nobody can trace to a reason is the first to get overridden, by a build partner or by me late in the day.

The brand section of the live showcase: positioning, brand heart, archetype, golden circle, audience, and voice scales

The strategic root

Positioning, archetype and audience sit on the same page as the tokens they produced.

Reasons it can act on

Why parchment and not white? The answer is one file away.

Step 02

The system defends itself.

The markdown specs give Claude Code and Cursor the brand at the start of every session. A pre-commit hook then audits each diff, and a check catches components that have no spec.

Every commit

Staged change
Pre-commit hook
Colour, type, spacing and components checked against the token list
Pass
Pushed
Fail
Blocked. A hardcoded hex or raw font-family gets the name of the token it should have used.

Component with no spec

Flagged
Written up against the template
Added to Figma

The spec check mattered most. Without it, the docs would always trail the code.

The live colour token grid, with every swatch read from the theme token file at runtime

Read from the source

Swatches read the token file at runtime, so the docs match what ships.

One colour, one job

The AI token marks Curator output, match scores and availability. Nothing else.

Step 03

The first version looked like AI output.

V1's strategy was right and its taste was wrong. Cream, champagne gold, a soft serif and lots of air is what a model reaches for when you say “elegant” and “wedding.” I'd built a system that stopped Claude inventing tokens, then shipped the palette Claude would have picked anyway.

V2 changed values only: cooler stone, near-black ink, lavender in place of gold, and lime for the AI signal. The token names stayed and no component code changed. V1 still ships behind a toggle.

Token values in the V1 and current themes
TokenV1V2Role (unchanged)
--color-ivory#faf6f0#f5f6f4Page background
--color-espresso#1e1510#0c1013Ink, primary buttons
--color-gold#b8944e#b3a3d4Accent: fills and icons
--color-slate#4a6b5a#8dc63fAI Curator, match, availability

V1: the default aesthetic

The colour token grid under the V1 palette: cream, espresso, champagne gold, slate green

V2: after the iteration

The same colour token grid under the current palette: cool stone, near-black ink, lavender accent, lime AI signal

Same page, components and token names. Only the values differ. Both ship, one toggle apart.

Step 04

The docs render the real system.

Every swatch, type step, shadow and component on the live showcase imports the code the app runs and reads the same token file. At Komodo, the docs were a separate artifact kept by whoever had deploy access, and they were often wrong.

Token file

Read at runtime

The app

Every component reads it

The showcase

Swatches, type, shadows, components, rendered live

Spec file (.md)

One concern per file

Claude Code, Cursor

Read it as a briefing

The documentation

The same file, not a copy

Flip the theme on the showcase and the docs flip with it.
Thirteen named typography steps, each specimen set in real product copy

Thirteen named type steps, each set in real product copy.

Input, textarea, and select components shown at rest, with a hint, and in an error state

Input, textarea and select, with every state spec'd in the file the component ships from.

Four elevation tokens rendered as soft diffused shadows rather than borders

Elevation instead of borders, from resting card to modal. A build partner will otherwise quietly break a rule like this.

Reflection

What I learned.

I now judge a design system by how quickly its users can make a correct decision. When one of those users is a language model, “correct” has to be machine-checkable.

I built the hook last. It should have been one of the first things, because I spent hours hand-reviewing diffs for stray hex values. I'd also version from day one. Freezing V1 before starting V2 is the only reason the before/after above exists.

The limit matters most. DSYS stopped the build partner inventing tokens. It couldn't stop me shipping the build partner's taste. A system enforces consistency and has no opinion on whether the result is any good. Catching that is still my job. The system let me act on it in an afternoon instead of a quarter.

Design SystemsAI Build PartnersDesign TokensClaudeCursorFigma MCPTailwind CSSBrand Identity