Lumen
An open-source design system for designers wearing too many hats. Twenty components, twenty-two tokens, and one opinion about how design and code should agree.
Handoff is a translation problem, and translation loses things.
A designer names a color "Primary / 600." An engineer names it --color-action. Same pixel, two names, maintained in two files that drift the moment either side moves. Multiply that by every token, every component variant, every state, and "design and engineering are out of sync" stops being a process complaint and becomes a math certainty. Nobody decided to drift. The structure guarantees it.
The usual fixes both have a tax. Adopt a big system (Material, a vendor kit) and you install a dependency, inherit someone else's entire opinion, and lock yourself to their release cycle and their idea of what a button is. Go the other way, utility classes, ship-it-yourself, and every consistency decision lands back on you, forever, with nothing holding the line.
And there's a quieter problem underneath both: most design systems look like each other. The same default surfaces, the same shadows, the same rounded everything. Having a point of view usually means being loud. I wanted the opposite, a system with an opinion you can feel but can't quite point to.
For a solo designer or a small team, the cost of building a "real" system is supposed to be prohibitive. The cost of not having one is just invisible, paid a little at a time, every handoff, forever. I built Lumen to stop paying it.
Make the design decision once, name it by what it means, and let that name be the same on both sides of the handoff. The system isn't a component library that happens to have tokens. It's a naming contract that happens to ship components.
Tokens, not utilities.
Twenty-two semantic tokens form the foundation. They're named for intent (action, surface, border-subtle), not for value (blue-600, gray-100). Change the decision in one place and it propagates everywhere that meant it, because the token carries the meaning, not just the color.
One vocabulary, both sides.
The twenty components are built on CVA, so every variant is explicit and typed, and the variant names in code are the exact names in Figma. A primary button is primary in both worlds. The handoff stops being a translation and becomes a lookup.
Copy, don't install.
Lumen isn't an npm dependency. You copy the components into your codebase and own them. No version lock, no waiting on a maintainer, no inherited release cadence. The code is yours the moment it lands.
Quiet by default.
The styling has a spine, hairline borders, restraint, room to breathe, but it's built to be a foundation you extend, not a look you fight. Opinionated enough to feel considered, neutral enough to disappear into your product.
Fewer "what did you mean by this token" round-trips, the token says what it means.
Copy-don't-install means nothing to lock or break on someone else's schedule.
Carrying the whole system, small on purpose.
Building on it.
Try it
Read the docs later. Touch a button first.
Every control here maps to a real token or variant. Change the variant, watch the code change with it; that's the Figma-to-code contract, live.
<Button variant="primary" size="md">
Get started
</Button>Reference build · real Lumen components drop in here
Every choice that makes Lumen good at one thing makes it bad at another. Here's where the seams are, because a system you can't see the limits of is a system you don't actually understand yet.
Copy-don't-install has no upgrade path.
The moment you copy a component, you've forked it. If I ship a fix upstream, you don't get it; you re-copy and re-merge by hand. I traded maintainability-at-scale for ownership-and-zero-lock-in. For a solo designer that's the right trade. For a fifty-person org, it might be exactly the wrong one.
The token layer assumes one brand.
Twenty-two semantic tokens encode a single point of view. True multi-brand theming, or full light/dark parity, would need a second dimension the foundation doesn't have yet. Right now "rebrand it" means editing tokens, not flipping a mode.
Twenty components is a starter, not a kit.
And the twenty I built are the easy twenty. No data table, no date picker, no combobox, which is to say the expensive, accessibility-heavy, genuinely-hard components are the ones still missing. The hardest 20% of the work is 100% ahead of me.
The naming contract is a handshake, not a lock.
Nothing enforces that the Figma variant names still match the code. It relies on discipline and a convention. There's no automated check that catches the two sides drifting, which means at scale, they eventually will.
“Quiet” is a taste, not a truth.
The restraint that makes Lumen feel considered also makes it wrong for any brand that needs to be loud. I designed for one kind of product. I should be honest that it's a kind, not the kind.
It's mine, with all that implies.
Built solo means it carries one person's opinions and one person's blind spots. No design review caught the thing I didn't think to question, because there was no one in the room to catch it. The open-source part is partly an attempt to fix that: other eyes, eventually.
It’s free. It will stay free. If it helps you, the only thing I ask is that you share it.
AAP Studio
An autonomous agent is only useful if you trust it. This is the review layer that earns the trust, read the plan, approve it, then let it build.
View case study→Product DesignGlass Box
People bet real decisions on what an agent did overnight. Glass Box makes every move readable, reversible, and sourced, without needing to read code.
View case study→Product DesignCalibrate
The first minute shouldn't teach the product; it should recognize the person. Calibrate tunes the feed by watching what you choose.
View case study→