
BookingHub Design System: One System, Two Surfaces

Executive Summary
My Role: Lead Designer, Design System Architect
Scope: Token architecture, component library, documentation across customer and admin surfaces
Scale: 6 foundation pages, 30+ components, 200+ token variables, 2 surface themes
Outcome: Single shared system powering both consumer PWA and 3-tier admin platform
At a glance
Built a design system from scratch for a multi-sided platform. One component architecture, two token sets, zero duplication. Customer surface in purple, admin surface in blue, same components powering both. 30+ components, 200+ variables, 6 foundation layers.
Before the system existed, both designers were making independent decisions on spacing, color, and component structure. The result was inconsistency across surfaces and repeated work for engineering when implementing similar patterns differently. The system was built to fix that, and to make sure it did not happen again as the product scaled.
How this started
BookingHub was never going to work without a design system. Two surfaces, two designers, one product. The complexity made a shared foundation necessary from the start.
Before any screen was designed, I made the call to establish the system architecture first. Token structure, naming conventions, foundation layers, all defined upfront so every design decision downstream had something to reference. I aligned the second designer and the engineering lead on this approach before building anything. Engineering's concern was whether one system could realistically serve two visually different surfaces without creating confusion in the codebase. Addressing that concern early, and showing how the token structure would map to their implementation, is what got buy-in for the single-system approach.
The goal was straightforward: no designer should need to make the same low-level decision twice, and no engineer should need to implement the same pattern twice.
The decision everything else was built around
Most design systems are built for one product with one visual personality. BookingHub was two products sharing one codebase. The customer surface needed to feel warm and consumer-friendly. The admin surface needed to feel structured and data-dense.

The obvious solution was to build two separate systems. I decided against it. 2 systems means double the maintenance, double the inconsistency risk, and two sources of truth that will inevitably drift apart. On a two-person design team with one engineering team, that was not a sustainable choice.
The decision was one system with two token sets. Same components, different values. A button is built once. On the customer surface it is purple. On the admin surface it is blue. The component does not change. The tokens do.
The trade-off was real: designers needed to know which surface they were working on before picking up a component. Accidentally using a customer token on an admin screen was possible and not immediately obvious. I handled this by making surface the first property you set when dropping a component. Customer or admin. Everything downstream follows from that one choice. Practical over perfect, and the right call for the team size and timeline.
Starting with foundations, not components
I started with color tokens and did not touch a single component until the foundation was solid.
Token naming took longer than expected. Getting the prefix structure right, customer/color/primary vs admin/color/primary vs shared tokens like color/feedback/success that belong to neither surface, required several iterations. That investment paid off immediately when components started. Every token reference decision was already made.
Typography, spacing, border radius, shadows, iconography, and color. All 6 foundation layers were locked before the first component was built.
Color token architecture: shared, customer surface, and admin surface

Building the components
Once foundations were solid, components moved fast. The hardest part was not building them. It was deciding what counted as a component versus a one-off pattern.
Non-negotiable on every component: auto layout throughout, all states defined, token-bound everywhere, 44x44px minimum touch target on anything interactive.

Impact
The system became the default for all new features across both surfaces. Engineers implemented new UI using existing components without requiring design input for each instance, which reduced back-and-forth on implementation decisions and sped up feature delivery. Inconsistency issues that had appeared in early screens, different spacing values for similar patterns, mismatched button styles across surfaces, stopped appearing once the system was in place.
The component library and token structure were subsequently reused in adjacent internal tooling built by the same engineering team. That reuse was not planned at the start. It happened because the system was documented clearly enough for another team to pick it up independently.
What the system actually solved
Designers stopped making inconsistent decisions, not because anything was mandated but because the system made the right choice the obvious one. That is what a good design system does. It removes low-value decisions so people can focus on the hard ones.
Both surfaces look like they belong to the same product. Different personalities, same DNA.