Lumen
Warp Design System · Case study · 2026

Warp · Design system · Live

Lumen.

I built Warp's design system on my own, and directed the AI that wrote most of the code. What's mine is the problem, the visual language, and every judgment call. The AI did the typing.

Role
Sole architect · product design engineer at Warp
Team
One designer, working with the founders, directing the AI agents that did the build
Context
Warp, a freight company that went AI-native and ran lean
Stack
Figma · DTCG JSON · Style Dictionary · shadcn registry · Next.js · Tailwind v4 · Playwright
Live
warp-lumen-design-guidelines.vercel.app
The Lumen Foundations reference: a Foundations, Tuned. card on the Obsidian canvas with the neutral, green, amber, and red color chips, a green LIVE marker, and a large Satoshi Aa labelled 300 to 900, OpenType.
The Lumen operator dashboard: an Acme Logistics workspace with a four-tile KPI row reading shipments today 1,284, on time 98.2 percent, average cost per pallet 42.10 dollars, active lanes 1,547, each with a green sparkline, above a shipments table with lane codes and dot-and-label status.
The Lumen iOS app: a Shipments screen with on time 98.2 percent and live 1,284 stat tiles and a list of freight lanes with status labels, in the same visual language as the dashboard.
One system, three densities. The Foundations reference, the operator dashboard, and the iOS app. One mood, one mark, one face, from marketing breath to operator dense.
00 The short version Thirty seconds

Warp ships fast, with a small team, across a lot of product and marketing surfaces. Each one had drifted into its own look. When I audited our transactional emails, I found three design systems running at once, with three different shades of brand green. Lumen makes them one, and it is built to be read by the AI agents writing most of the code, not only by people.

900+
Design tokens
98
Component contracts
9
Platform emit targets
35
Decision records
16
Audit rounds

Built solo, with the AI doing the typing. These are the size of the system, not a claim about its impact.

01 The problem Why Lumen exists

Three ways the same brand kept coming apart.

Warp had a brand: a loud green and a dark, dense operator feel. What it did not have was the layer that turns a brand into a system, the part that makes every screen agree with the next one.

01
Primitives forked silently.
Every team rebuilt the same pieces, because nothing canonical existed to copy. Each PR that duplicated an old pattern locked in someone's one-off, and the greens and the card styles quietly forked apart.
02
Tokens changed, the prose did not.
When we retired the green glow on the shadow tokens, the token check passed. Every doc still taught the old rule, so agents read the docs and built the retired glow right back into the code. A check on the tokens cannot see a sentence.
03
Being legible to a machine was an afterthought.
Cursor, Claude, Copilot, and Codex touched our UI every day. None of them had a contract they could read, so they wrote what their training suggested, a generic SaaS look, not Warp. The system had to be legible to a machine first, then friendly to a person.

The audit · transactional email Three CTAs, three greens

One brand, three greens, in the same channel. #4ADE80 was Warp's accent lime and #22C55E its success green; #00FA8A is the Spring Green they were unified into. A diagram of the real finding, drawn from Warp's own brand values, not a screenshot.

The fragmentationThree greens, three systems, one surface. Nobody did anything wrong. Each was a fossil of a moment when someone had to ship and could not find a convention to copy.
02 The synthesis Apple and Warp, stacked

I stopped choosing between clean and dense.

The brief asked for Apple: clean, minimal, Ive and Rams. Warp's real character is a freight Bloomberg terminal, dark and dense and full of live numbers. Those are not opposites. They live at different layers, so I stopped choosing and started stacking them.

Apple discipline
How the system behaves.

A 1.25 modular type scale, tight tracking on display. A 4-point base on an 8-point soft grid. Hairlines carry separation, and shadows are reserved for UI that genuinely floats. Motion decelerates and stays under 200 milliseconds.

Warp substance
What the system is made of.

An Obsidian #0D0D0D canvas, neutral where red equals green equals blue. Spring Green #00FA8A, one role only. Satoshi for every job, its tabular figures carrying the numbers, no second font.

The resolutionDiscipline on top, substance underneath. Apple is the behaviour, Warp is the material, and Lumen is the place they meet.
03 Foundations One mood, one mark, one face

A palette kept small on purpose.

Three families of color, one typeface, one grid. A single accent only reads as loud when nothing around it competes, so I gave it nothing to compete with.

Color Drawn from the real token ramps

Obsidian · the canvas rampPaper → void · R = G = B
Neutral · paper + cool graysHierarchy, never loud
Accent · Spring GreenThe only loud color
Status · dot + label, never hue alone
Live / success At risk Late / error

The dark stops are a true neutral, red equals green equals blue, so nothing tints the canvas green. The accent was retuned from the old Warp lime to #00FA8A; the discipline, one hue in one role, is the part that was mine.

ColorObsidian, neutral, accent. The canvas is a true neutral near-black with no green tilt. Cool grays do the hierarchy, and the accent shows up in fills, borders, and text, never in light.
The accent
One role, and nowhere else.

Spring Green was already Warp's brand color, used hundreds of times in the code before me. My part was the discipline. It means action, live, or success, and it appears nowhere else on the surface.

The face
Satoshi, every job.

One variable family carries interface, display, body, and numerals, at weights 300 to 900. The monospaced feel on numbers comes from OpenType features on that same face, so there is no second font. That one call cut four families to one.

Type · Satoshi Set live, in the face it describes

SystematizedDisplay · 64
Operator consoleTitle · 40
Every screen agreesHeading · 26
One face carries every jobBody · 17
SatoshiLight 300 SatoshiRegular 400 SatoshiMedium 500 SatoshiBold 700 SatoshiBlack 900
Tabular figures · digits stack
$1,343.50$42.10$1,547.00
LAX SFO · ETA 12:00:06 · WRP-9824
TypeSatoshi, 300 to 900. The numbers ride on OpenType tabular figures, so a column of freight rates stacks digit over digit with no second font loaded.
One source, nine emit targets. Style Dictionary
01Web, React
02iOS, SwiftUI
03Android, Compose
04React Native
05macOS desktop
06Windows desktop
07Shopify Liquid
08BigCommerce
09WooCommerce

Honest about coverage. The tokens and the consumption guides reach all nine targets. The native component examples are a partial proof of concept so far, not nine finished apps.

04 Reference templates Same language, different density

Eight surfaces that answer one question.

Each template is the canonical answer to "is this how a Lumen surface looks?", from marketing breath all the way to operator dense.

01
Marketing and Landing
A type-led hero, a screenshot standing in as proof, and a live rate ticker. Apple-disciplined chrome over Warp-substantive content.
02
SaaS Dashboard
The operator-portal pattern. Sidebar nav, a KPI grid with sparklines, a sortable table, and a live activity rail. Dense and scannable.
03
Web Tool
A single-purpose utility: preset rail, focused canvas, control panel, output panel. The pattern for any calculator or one-shot job.
04
Commerce
Storefront patterns for Shopify, BigCommerce, and Woo. A product page with variant pickers and a drawer cart, on the same Lumen type discipline.
05
Mobile
iOS and Android side by side. Same visual language, platform-native chrome: Apple HIG on iOS, Material 3 on Android. Same tokens, different mappings.
06
Native Desktop
macOS and Windows window chrome, with vibrancy and Mica titlebars. Where the future SwiftUI and WinUI adapters land.
07
Foundations
The system's first principles: color ramps, type scale, spacing, elevation, motion. The route everyone reads first.
08
Library
Every primitive in at least one default state, and every variant. The "is this how a Lumen X is supposed to look?" reference.
The real Lumen SaaS Dashboard render: a left sidebar for Acme Logistics, a KPI row reading shipments today 1,284, on time 98.2 percent, average cost per pallet 42.10 dollars and active lanes 1,547, each with a green sparkline, and a shipments table with WRP lane codes and dot-and-label status for on time, pickup, at risk, late, and delivered.
Template · SaaSThe operator portal. Right-aligned tabular numbers, hairline rows, and status shown as a dot and a label. The register the whole system was built to serve.
The real Lumen Commerce render: a Foundry storefront product page with a gallery on the left and, on the right, the title Field Jacket Mk II, a price of 248 dollars marked down from 320 with a 22 percent off tag, olive-drab color and size pickers, and a bright green Add to cart button showing 248 dollars.
Template · CommerceThe same discipline, on a storefront. A product page held to the Lumen type scale, with the accent doing the one job it always does: the buy action.
The real Lumen Mobile render: an iOS iPhone and an Android phone side by side, both showing the Shipments list. iOS has a large title, on time 98.2 percent and live 1,284 stat tiles, and a bottom tab bar; Android has a top app bar, a green New shipment button, and a bottom navigation bar. Both share the Lumen visual language.
Template · MobileiOS and Android, one language. Apple HIG on the left, Material 3 on the right, same tokens mapped to each platform's own chrome.
05 LLM-first The schema is the source

Documentation an agent can follow tightly.

Most design systems are documentation that engineers translate into code. Lumen flips it. The schema is the source, and every AI tool gets a contract it can read in its own format.

Two files per component
Human beside machine.

A component.md with anatomy, usage, motion, and accessibility that a designer reads directly. A component.json the shadcn registry installs from. They are kept in lockstep, so the prose and the schema never drift apart.

One layered contract
Every agent, its own format.

An llms.txt for discovery, an AGENTS.md for the universal rules, then tool-specific files for Claude, Cursor, and Warp. All of them mirror one source, and the rules are enforced by lint.

The component contract Two files, kept in lockstep by CI

button/component.md
--- frontmatter ---
name: Button
status: stable
 
## Anatomy
Label, optional icon, one action.
## Usage
One primary action per view.
## Motion · A11y
Decelerate < 150ms, native focus.
button/component.json
{
  "name": "Button",
  "version": "0.12.2", "status": "stable",
  "props": {
    "intent": { "type": "enum", "values": ["primary", "ghost", …] },
    "size": { "type": "enum", "values": ["xs""xl"] }
  },
  "tokens": { "consumed": ["color.action.primary.bg.rest", …] },
  "a11y": { "role": "button" }
}
llms.txt· AGENTS.md· claude · cursor · warp one source, lint-enforced

The .md is what a designer reads; the .json is what the shadcn registry installs from. Every AI tool gets the same rules in the format it reads natively, and a lint fails the build when the prose and the schema drift apart. Both panels are abbreviated from the real button/component.json and .md, in their own field shape.

The contractReadable by a machine first. On a team where the agent usually holds the keyboard, the spec an agent can follow is the spec that actually ships.
06 R1 to R16 Vigilance, retired

Bugs hide from the same kind of looking.

Most systems drift because they lean on people remembering the rules. I replaced that with checks the build runs on its own. Each round added a new kind of measurement, and a new kind of measurement is what kept surfacing a new class of bug.

R1–R3
Static, interaction, contractSticky-header bleed, product-page pickers failing the first click, hardcoded calendar offsets. Per-route audits.
R4
Meta-contract integrityVersion chips drifting across llms.txt, the using guide, and the readme. A release step rewrites them in lockstep.
R5–R6
Mobile metrics and single-source docsAudits at 320 and 375, catching layout inflation, then a catalog that disagreed with itself on how many components existed.
R11
Green retired from every shadowBrand identity is a green fill, never a green light. A lint walks the token JSON and fails the build on any accent in a shadow.
R14
Docs-to-tokens driftThe token check could not read prose. A second lint walks every doc and fails the build on any prescriptive use of a retired token, off a list, so the next retirement is one line, not two hundred find-and-replaces.
R16
A contrast bug becomes a guardMy own operator tool, built on Lumen, shipped text at 1.66:1 on green across 11 or more sites, because a developer reached for a token name that did not exist and it fell through quietly. I added the token, a defensive component, a build-failing check, and a doc. On its first run the new check caught the same bug hiding in Lumen's own example code.

Guard · contrast ADR 0035 · the bug that wrote its own lint

1.66:1 · Fail
14.7:1 · Pass AAA

My own operator tool shipped 1.66:1 text on green across eleven or more sites, because a developer reached for a token name that did not exist and it fell through quietly. I added the token, a defensive component, a build-failing check, and a doc. On its first run the check caught the same bug hiding in Lumen's own example code.

Guard · Contrast1.66:1 to 14.7:1. Fixed at the system level across every affected site, then wired into a check so it cannot come back.

Guard · elevation ADR 0030 · I overruled my own system

Retired a green glow, drawn to show the wrong
Current flat surface, neutral shadow

I had built an internally consistent rule that allowed green in a button's halo, then reviewed it against the live product and decided colored light reads cheaper than a clean surface. So I overruled my own system, broadened the lint to fail the build on any green shadow, and shipped the code, the docs, and the amended rule in one commit. The whole page you are reading obeys it.

Guard · ElevationThe accent left the light. Colored glow reads cheaper than a clean surface, so I retired green from every shadow and made the check fail the build on any that return.
A rule you have to remember is a rule that decays.
One check on the tokens, one on the prose, because neither can see the other.
07 Three primitives Where the feeling lives

A number, a live dot, a rate ticker.

An operator sees three small pieces of Lumen far more than any button. That is where the operator-console feeling comes from, so they got most of the polish.

01
Numbers as hero
Big bold tabular figures with a small tracked unit, right-aligned in tables so the digits stack. The most-read element on any operator surface.
02
One signature pulse
An 8-pixel filled green dot with a 2-pixel ring, pulsing on a slow ease-out loop. It is the only ambient motion in the system, it runs only when something is genuinely live, and it honors reduced motion.
03
The marquee that earns its keep
A horizontal stream of freight-lane rates in tabular figures, on a slow continuous loop. It says operator console louder than any hero image could.

The three signatures Where the operator mood lives

Shipments today
1,284
▲ +12.4% wow
Live
the only ambient motion, a 3s pulse
Rate ticker · freight lanes
LAX→SFO $262 ORD→ATL $485 DFW→PHX $390 SEA→DEN $612 MIA→JFK $724 BOS→CLT $540
The primitivesStat, LiveDot, RateTicker. The pieces an operator reads a hundred times a shift, so care shows up here as speed and legibility, not decoration.
08 Honesty What it is, and what it isn't

Coherence and defects prevented, not a dollar figure.

Lumen is live, and it runs real work. Our operator tool is built on it, and the team's AI agents read from it directly. What it does not have is an adoption chart or a revenue line, and I am not going to draw one.

What I can prove
  • The size of the system, all built solo with the AI doing the typing: 900+ design tokens, 98 component contracts, 9 emit targets, and 35 written decision records.
  • A 16-round audit where I changed the measurement each round instead of re-walking the same screens. It kept finding a new class of bug.
  • On the reference build Lab: page load down about 31 percent, layout shift at zero, and zero unnamed controls across 714 interactive elements. Lab numbers, and I label them that way.
  • The contrast bug my own tool shipped, fixed at the system level from 1.66:1 to 14.7:1 across every affected site.
What I will not claim
  • Adoption numbers. Real adoption is our tool running on it and the agents reading from it, not a count across all of Warp.
  • Revenue or conversion. This is internal platform work. It buys coherence and prevents defects, and I do not get to invent a dollar figure for that.

The honest value here is coherence that holds on a shrinking team, and defects caught before they ship. That is what a design system is for, and it is the part worth judging.

09 Reflection What building it taught me

Vigilance is the wrong currency for consistency.

The lesson
On a team that keeps shrinking, and writes more of its code with AI every month, nobody has the attention to police a convention. So you encode the rules you care about, or you watch them decay.
The invisible work
Every decision I cared about had to become three things at once: a token, a written record, and a check the build runs on its own. The whole thing had to be readable by an AI agent first, because on this team the agent is usually the one holding the keyboard.
The bar
I would rather call Lumen rigorous and honest than finished and perfect. The scar tissue, the bugs it found in itself and then made impossible, is the part I am most proud of.
The system, end to endEight surfaces, one language
Lumen Foundations reference surface
01 Foundations
Lumen Marketing and Landing surface
02 Landing
Lumen SaaS Dashboard surface
03 SaaS
Lumen Web Tool surface
04 Tool
Lumen Commerce storefront surface
05 Commerce
Lumen Mobile surface, iOS and Android
06 Mobile
Lumen Native Desktop surface, macOS and Windows
07 Desktop
Lumen component Library surface
08 Library
Eight surfaces, one system. Foundations, Landing, SaaS, Tool, Commerce, Mobile, Desktop, and Library, all speaking the same language at very different densities.