Building, Repairing,
and Converging Design Systems
Built Zappos's system from zero, repaired Shopbop's drift from code, and cut duplicate design effort across both brands
Background
Zappos and Shopbop landed on my plate at the same time with mirror-image problems. Zappos had just rebranded and had no design system file to build with: five disconnected Figma files, all claiming to be the source of truth. Shopbop had a system that was years old and had drifted so far from its own code that the library was actively misleading the people using it.
Owning both at once made each brand a control group for the other: Zappos showed year one of a system's life, Shopbop showed year five if one specific gap goes unaddressed.
Zappos: no library at all
- 5 disconnected Figma files with scattered elements
- Varying designs, no source of truth
- Pre-rebrand elements still in use
- Broken library references
- No tokens, no documentation
Shopbop: a library not aligned with code
- Years of accumulated drift
- Deprecated components mixed with live ones
- Components not optimized or scalable
- External library dependencies nobody owned
- No tokens, no inventory, no changelog
Impact
Both systems shipped and are in active use; the convergence work is designed and handed off for the homepage and PLP, with the app-side foundation still in progress.
Approach: build, repair, converge
Starting point
Zappos rebranded in Q4, and the brand shipped before a system to build with it existed. By January there were five files, broken references between them, and old fonts still in active use. Designers were shipping screens that looked fine individually and inconsistent as a set, and the cost was compounding: every screen shipped in that state made the next one more expensive.
Prioritization
Zappos and Shopbop both landed on my plate in January, but I didn't work them in parallel. Zappos had nothing, and designers were shipping divergent screens every week, and the cost was compounding daily. Shopbop's system was wrong, but stably wrong; it had been wrong for years, and one more quarter wasn't going to change that. I sequenced Zappos first and started Shopbop in April, once the Zappos core was built out. With no product manager on either system, that sequencing call was mine to make.
Token architecture
The fast path was to rebuild the paint styles as one clean set and call it a system. Instead I built a semantic token layer, organized by role rather than by value. border-subtle is something a designer and a front-end engineer can actually disagree about; it moves the review conversation from "which gray" to "what is this border for." A role-based layer is also the seam where a second brand can be swapped in without touching a single component; in January that was a hedge. By August it was the thing that made convergence possible.
The tradeoff was real: semantic tokens are slower to author and force a vocabulary on people who didn't ask for one. I paid that down with an in-file tutorial and 6 token reviews with design and engineering. Notice where tokens land in the release order below: fifth. Four releases of components had already gone out, which meant rebinding the entire library in one pass. I could have built tokens first on a correct foundation, but that's three or four months with nothing in anyone's hands. I chose adoption first and paid for it with my own rebind pass.
Zappos primitive palette. Yellow-300 is the exact brand yellow, carried through as a UI primitive.
Governance
Design systems don't usually fail because of bad components. They fail when the library ships once, quietly stops being correct, and people go back to copy-paste. There was no product manager on either system, on either brand, so the roadmap, release sequencing, prioritization, and communications were mine. The governance layer was the product management function these systems didn't otherwise have.
- A public Slack channel instead of DMs, so answers accumulated instead of evaporating
- A release note every time, so nobody had to diff a library to find out what moved
- An in-file onboarding tutorial so a new designer could self-serve on day one
- Weekly UX syncs, org-wide demos, monthly roadmap reviews, standard operating procedures, office hours
Collaborators
Results
First-year insertions by type: components ~29K, styles ~51K, tokens ~188K. Token insertions are the strongest adoption signal: they show the semantic layer is what designers build on, not shelfware they route around.
"Thank you for creating the design system that makes my daily workflow a billion times more efficient." UX Designer, Zappos
Partnered with 2 engineers to build the Zappos semantic tokens into the codebase. The token architecture is implemented, not just documented in Figma.
Dev resourcing for component build-out never materialized. Storybook still isn't aligned to the library, and developers still ship one-off components.
In January the priority was fixing weekly design divergence, which a Figma source of truth solved. In hindsight, the component gap should have been raised as a scoped, costed ask to the people holding headcount, not a status update. Tokens got resourced partly because they were a small, well-specified thing to approve. A widely-adopted component library on an unaligned codebase drifts even as adoption climbs; I'd already seen that failure mode on Shopbop, five years in.
Starting point
Shopbop's system existed, was years old, and had drifted badly from the Storybook package it was supposed to describe: deprecated components sitting in the file indistinguishable from live ones, external dependencies nobody on the team controlled. The failure mode here wasn't absence, it was false confidence: a designer specs a component in good faith from the library, hands it off, and the engineer builds something different because the library was wrong and neither of them knew. Every handoff was paying a tax nobody had budgeted for.
Collaborators
Design-to-code alignment
Code is what customers receive; design intent that never shipped and outdated Storybook sections aren't the source of truth. The obvious fix for naming mismatches, renaming the Figma components to match code, breaks every instance in every consuming file and erases history engineers rely on. Instead, I documented the mismatch: every component now carries the name of its code counterpart in the file, turning handoff ambiguity into a lookup.
Shopbop's real SEAM component library palette, audited during the migration
Migration
24 legacy paint styles were deleted and migrated to variables, with every fill, stroke, and text node rebound. Deleting styles other people depend on is a consent problem as much as a technical one. 4 discovery sessions and 5+ reviews with the same engineers are why the file was trusted the day it published, rather than three months later.
This was sized in January, before the work started, from what the file looked like rather than from what an audit would find. Opening it up in April surfaced debt deeper than that estimate assumed, most of it pre-existing, but "wrong for legitimate reasons" still put partners' plans against the wrong number. Going forward, that means re-forecasting out loud as findings land, with the specific finding attached, rather than holding a date until it collapses.
Context
Two brands running two systems meant duplicated effort on every foundational decision and a blocked path to a unified codebase. Converging them was a company-wide goal, timed with a company-wide push on AI tooling; the direction the group was leaning toward, me included, was an AI-native, code-first system built from scratch with no Figma layer at all. I operated as the main individual contributor on this piece, with one senior designer from each brand for review and planning. What hadn't been tested yet was whether building from scratch was actually necessary.
Validating the direction
Engineering surfaced the candidate that changed the direction: an existing Amazon component library. I audited both brands' actual needs against it (core components, PDP, PLP) and used AI tooling to apply Zappos and Shopbop token assignments onto its token system, generating themed component visualizations for both brands off one component base.
Both brands held up as recognizably themselves, with nothing built from scratch. The team moved off the from-scratch direction onto that foundation, and I produced five deliverables against it: a token system developer reference mapping to both brands, a component analysis, and recommendations for nav, PDP, and PLP.
Interim solution
The target is a converged homepage in September. Shopbop has no semantic token layer at all; Zappos does, since two engineers had already built it out in code back in Act I. So the interim path is simple: Shopbop implements that same architecture with Shopbop's values. The September launch isn't blocked by UX; on web, it's recreating what exists today.
This runs as two tracks: stretch the architecture that already exists in production so the dated web launch can proceed, and build the brand-agnostic foundation, shared primitives and semantic tokens, on the app's own timeline, where nothing is blocked on it. A token layer built as a hedge in January, on a brand I'd been working on for three weeks, is what's unblocking a second brand's launch in September, because the role-based architecture left room to add a second brand without rework.
Current status
The shared token system and converged components for both the homepage and PLP are designed and handed off, past the recommendation stage. The brand-agnostic foundation for the app is still in progress.
Personal takeaways
Architectural decisions buy options, not just outcomes. The token layer built as a hedge became a second brand's answer eight months later.
Adoption is a governance outcome, not a launch outcome. The changelog and the standing review cadence are what sustained usage past month six.
When design and code disagree, code wins, and documenting the mismatch scales better than hiding or force-fixing it.
"We need to build this from scratch" is a testable claim, not a premise. Validating whether existing infrastructure can stretch costs days and can save a quarter.
The gap I'm watching closest: Zappos's token layer got engineering investment and its component layer didn't, partly because I packaged the token ask as scoped and costed and the component ask as a status update. That same gap now exists on an adopted Shopbop library sitting on an unaligned codebase, a pattern worth catching earlier next time, since adoption metrics can look healthy while the gap underneath widens.