Skip to content
← All work
QZee One

How do you let humans and AI build faster without letting a growing product ecosystem drift?

I created QZee One from scratch as the shared design operating system for QZee, then defined the human, machine, contribution, accessibility, and migration workflows needed to make it usable across products.

Project frame: QZee One: turning 4,000+ hardcoded values into an AI-enabled design system

Scope note: System figures come from the reviewed QZee One registry and build outputs. Storybook accessibility results apply only to the displayed story; Stable promotion still requires manual assistive-technology evidence.

Role
Co-founder & Product Design Lead
Team
Co-founder · Product engineering · AI-assisted implementation
Year
2026 · active system
Platform
Web · React Native · Email · Marketing · AI agents
0 → 1
system creation

I created QZee One from scratch, then used its contracts to migrate older products incrementally.

Human + machine
two interfaces

People use the portal and Storybook; agents use the same reviewed system through a registry, generated health, and a read-only CLI.

Bounded
AI workflow

Agents can discover context and propose scoped changes, while prioritisation, lifecycle, merge, and release authority remain human.

Observable
system health

Channel support, ownership, evidence currency, and known gaps are generated from reviewed records instead of being hidden behind component counts.

QZee One design-system portal showing its semantic core connected to web, apps, email, marketing, and physical brand touchpoints
QZee One gives the system a human front door. The portal connects foundations, product patterns, channel coverage, health, and adoption guidance.
01 · Context

The problem

QZee had grown through multiple products and channels before it had one design contract. Audited codebases contained more than 4,000 hardcoded colour values, while two brand limes, four type scales, and incompatible slot palettes were live at the same time. Creating another component library would only centralise part of that problem. I needed a system that could express shared product intent across platforms, guide the migration of older products, and give both people and AI enough governed context to contribute without creating a new form of drift.

02 · Evidence

What shaped the direction

Product drift was already measurable

The audited products contained two live brand limes, four type scales, incompatible slot palettes, and more than 4,000 hardcoded colour values.

One web library would not cover the product

QZee needed shared intent across customer and owner web products, native apps, transactional email, marketing, partner brands, and future physical touchpoints.

White-labelling could not assume a safe brand colour

Third-party brands can supply any sRGB primary. Reusing that value unchanged for buttons, links, selected states, and focus would create contrast and interaction failures.

AI needed structured context, not a larger prompt

An agent could read code but could not infer approved intent, lifecycle, ownership, channel parity, or whether evidence was current. Those decisions had to become explicit data.

Legacy migration could recreate the same drift

Older products needed an incremental adoption path with fixed compatibility checks, package-version visibility, and named exceptions rather than a risky big-bang rewrite.

03 · Process

How it came together

Starting with drift, not a component inventory

QZee One began as a zero-to-one system, but the products it needed to support already existed. The audit exposed more than visual inconsistency. Two versions of the brand lime were live, typography had split into four scales, scheduling surfaces used incompatible slot palettes, and more than 4,000 colour values had been hardcoded across the reviewed codebases.

Those symptoms pointed to a missing product contract. If I began by drawing a large component inventory, I would reproduce the same decisions in a more central place. I began with the roles the products needed to express: page and card surfaces, primary and secondary text, status, focus, action, time-slot state, tenant accent, motion, spacing, and hierarchy.

Defining one semantic contract across different channels

I structured the token model in three layers. Core values contain the raw ingredients. Semantic tokens describe intent. Domain tokens add meaning for specialised product states such as booking slots. Products consume the semantic and approved domain layers; they do not reach back into a core colour ramp.

The contract then emits the form each channel needs: CSS custom properties and typed modules for web, theme objects for React Native, constrained rendering rules for email, and reusable compositions for marketing. The goal was not to force identical pixels across every touchpoint. It was to preserve the same meaning while letting each platform behave natively.

System architectureOne contract · two interfaces

Human interface

QZee One

Foundations, health and adoption

Storybook

Components, states and guidance

Contribution intake

Problems, evidence and ownership

1

Shared contract

Semantic tokens, policies and asset records

Core → semantic → domain. Products consume roles, not raw values.

Machine interface

Registry

Lifecycle, channels and evidence

Read-only CLI

Search, inspect and diagnose

Generated health

Deterministic JSON and reports

Web
React Native
Email
Marketing
The same reviewed contract serves people and software. Humans get explanation and exploration; agents get deterministic context they can inspect without inventing a parallel design language.

Making any partner colour safe by design

Third-party branding was not a palette swap. A partner could supply any valid sRGB primary, including a pale yellow, a deep blue, or a mid-tone pink. Applying that value directly to buttons, links, selected states, text, and focus rings would make the same brand readable in one context and fail in another.

I treated the supplied colour as source material. At runtime, QZee One reads the active page and card surfaces, then derives eight semantic roles: accent fill, pressed fill, control boundary, soft wash, soft border, on-fill text, on-soft text, and link. Content on the main fill resolves to dark ink or white, whichever clears 4.5:1. Brand-coloured text is adjusted until it clears 4.5:1 against its surface, while non-text control boundaries clear 3:1.

White-label contractOne colour · eight accessible roles
  1. 01

    Partner input

    One valid brand colour

  2. 02

    Read context

    Current page and card surfaces

  3. 03

    Derive roles

    Eight accessible theme values

  4. 04

    Apply safely

    Components consume intent

Yellow

Input #FFCC00

Any sRGB
Book this service10.79:1

On-fill text: Dark ink

Pressed

#e0b400

Soft state

Selected

Link on surfaceVenue details

Blue

Input #0057FF

Any sRGB
Book this service5.52:1

On-fill text: White

Pressed

#004de0

Soft state

Selected

Link on surfaceVenue details

Pink

Input #FF2D8D

Any sRGB
Book this service4.67:1

On-fill text: Dark ink

Pressed

#ff469b

Soft state

Selected

Link on surfaceVenue details

Allowed to flex

Fill, pressed, boundary, soft wash, soft border, on-fill text, on-soft text and link

Text roles clear 4.5:1. Control boundaries clear 3:1 against both the page and card surfaces.

Protected from branding

Keyboard focus

Focus stays fixed blue. Surfaces, status and structural text stay system-owned.

A partner colour is treated as source material, not a finished interface token. The runtime derives the role set against the active surfaces, while focus, status and structural colours stay protected.

The allow-list was as important as the derivation. Partner branding can change the accent role set, but it cannot change page and card structure, status meaning, primary text, or the focus ring. Focus stays a fixed high-contrast blue, preventing a pale partner colour from making keyboard position invisible. When the theme changes, the tenant roles are re-derived against the new surfaces rather than carrying light-theme assumptions into dark mode.

Designing a system for people and AI

The AI-enabled layer was not a prompt that generated arbitrary interface code. I treated AI as another system consumer. To contribute safely, it needed to know which asset was approved, where it could be used, who owned it, what lifecycle it was in, which channels it supported, what evidence existed, and where the known gaps were.

The registry makes those facts machine-readable. Generated JSON exposes health without creating a second hand-edited truth, while the zero-runtime-dependency CLI can search by task intent, inspect a component or channel, find documentation, report system health, and diagnose a consumer's declared package exports. Search is deliberately deterministic lexical ranking rather than an unverifiable remote model.

AI-enabled workflowConstrained autonomy
  1. 01

    Product issue

    Evidence and allowed paths

  2. 02

    Human triage

    Agent-ready only after review

  3. 03

    Read-only discovery

    CLI, registry and health

  4. 04

    Draft change

    One scoped task and early PR

  5. 05

    Quality gate

    CI plus accountable review

Human authority stays explicit

PrioritisationDesign intentLifecycle promotionMerge and release

Current safety boundary

Agent-authored draft publication remains disabled until branch protection can enforce the boundary. Release automation is signal-only and never edits a consumer repository.

AI can discover the system, take a prepared task and propose a change. It cannot define its own scope, bypass evidence, merge, deploy or treat generated output as approval.

This is constrained autonomy. A product issue must be human-triaged before it can become agent-ready. Scope and allowed paths must be explicit, and the agent must stop if human work overlaps. Prioritisation, lifecycle promotion, merge, secrets, and deployment remain outside its authority. The architecture enables AI contribution without confusing speed with approval.

Making Storybook the component workshop

QZee One is the front door for foundations, channels, system health, and adoption. Storybook is the focused workshop for the web component contract. Stories sit with their components, use the same semantic roles, switch between light and dark schemes, expose typed controls, and generate reference documentation from the public API.

QZee-branded Storybook documentation for the Button component, showing the live primary variant, controls, variants, and component navigation
The QZee-branded Storybook keeps API guidance, states, live controls, and implementation examples beside the component.

I kept the distinction between demonstration and governance clear. Storybook shows the component contract and gives authors rapid feedback. Tests govern behaviour, and the registry records lifecycle, channel support, evidence, and ownership.

Turning component requests into governed submissions

The submission flow starts in the repository that owns the product problem. The proposer must describe the need, identify the existing token, component, pattern, or template they considered, and explain why it is insufficient. They also name the affected channels, expected consumers and paths, acceptance evidence, and whether the work could later be prepared for an agent.

Contribution workflowProblem-first component submissions
  1. 01

    Frame the problem

    Describe the user or team need in the product repository.

  2. 02

    Check the contract

    Show why an existing token, component or pattern is insufficient.

  3. 03

    Define scope

    Name channels, consumers, ownership, paths and acceptance evidence.

  4. 04

    Build in context

    Cover themes, tenant safety, interaction states and Storybook.

  5. 05

    Record evidence

    Add behaviour, accessibility and registry evidence for the target lifecycle.

  6. 06

    Review and release

    Pass CI, human conformance review, changeset and migration guidance.

A request does not begin with “build this component”. It begins with the product problem, the existing contract and the evidence needed to justify a shared addition.

During build, the component contract requires every relevant interaction state, semantic tokens only, both themes, tenant safety, keyboard behaviour, accessible names and states, strict types, tests, Storybook guidance, and a registry record. A published behaviour change also needs a changeset and a migration path. This keeps the system focused on repeated product needs instead of accumulating speculative primitives.

Treating accessibility as evidence, not polish

Accessibility starts in the foundations. The token build checks 94 foreground-and-background relationships in light and dark themes against WCAG 2.2 thresholds. It also prevents raw colours, locks light and dark token shapes, keeps a high-contrast focus colour fixed, respects reduced motion, and derives safe foregrounds for tenant accents.

At component level, tests cover roles, accessible names, keyboard paths, focus movement, announcements, disabled and busy states, and native accessibility properties. Representative compositions run structural axe checks, while real browser contracts cover narrow reflow, zoom, visual viewports, safe areas, and nested modal focus.

QZee Storybook Button variants with the accessibility panel reporting zero violations and five passed checks for the displayed story
Storybook gives authors immediate axe feedback on the selected story. This capture is evidence for that Button composition, not a claim that automation certifies the whole system.

I explicitly did not present automation as certification. Complex assets cannot become Stable without recorded manual keyboard, 200% and 400% zoom, forced-colour, VoiceOver, NVDA, TalkBack, and relevant real-device evidence.

Building one release contract and a fixed workflow checker

The root pnpm run ci command is the release contract. It validates tokens, registry data, consumers, CLI behaviour, dependency boundaries, token usage, changesets, strict types, package output, interaction and coverage tests, Storybook, the QZee One portal, and deterministic browser contracts in real Chrome. Pull requests and release automation run the same contract used locally.

Release contractCI and workflow checker
  1. 1

    Foundations

    • 94 contrast pairs
    • Theme shape lock
    • No raw colours
  2. 2

    Component contract

    • Strict types
    • States and keyboard
    • Structural axe
  3. 3

    Real browser

    • 320px reflow
    • 200% zoom
    • Safe areas and focus
  4. 4

    Consumer check

    • Locked install
    • Version alignment
    • design-system:check
  5. 5

    Release

    • Changeset
    • Package build
    • Migration notes

Automation is evidence, not accessibility certification.

Complex Stable assets still require recorded keyboard, 200% and 400% zoom, forced-colour, VoiceOver, NVDA and TalkBack checks.

The same release contract runs locally, in pull requests and before publication. Consumer repositories add a fixed compatibility check, so adoption drift is visible without allowing arbitrary remote commands.

Each active product exposes one design-system:check script and calls a central compatibility workflow. That workflow installs from the product's lockfile, compares declared, installed, and release-expected package versions, then runs the fixed check. It cannot accept a caller-supplied command. Release-triggered version drift can create or update one adoption issue; an ordinary pull-request failure cannot fill the backlog with duplicates.

The current automation mode is intentionally signal-only. It can show that a consumer has fallen behind, but it does not edit that product or open an autonomous change.

Migrating older products without a big-bang rewrite

Creating the system from scratch did not mean rebuilding every QZee product at once. I treated migration as a sequence of owned journey boundaries. Each legacy surface was audited, mapped from local values and patterns into semantic roles, then moved onto released packages where the contract was understood.

Legacy migrationIncremental adoption
  1. 01

    Audit

    Find raw values, local patterns and incompatible foundations.

  2. 02

    Map

    Translate product intent into semantic roles and shared contracts.

  3. 03

    Replace

    Adopt packages incrementally at an owned journey boundary.

  4. 04

    Verify

    Run the consumer compatibility workflow against the locked product.

  5. 05

    Track

    Turn remaining exceptions into named gaps with owners and evidence.

QZee One was created from scratch, but adoption was not a big-bang rewrite. Older products moved onto the contract journey by journey, with compatibility checks and explicit exceptions keeping the transition observable.

The compatibility workflow made each step observable. Where a product could not adopt the shared contract yet, the exception became a named gap with scope, ownership, and evidence rather than another silent local pattern. This let the system grow while older products continued to operate.

Publishing the system's actual health

Component totals are easy to celebrate and easy to misuse. I built the health model to answer harder questions: is the asset supported in every required channel, is the evidence current, who owns the gap, and has the asset genuinely met the bar for its lifecycle?

QZee One system health view showing required channel parity, current evidence, named gaps, governed assets, mapped exports, and asset-level status
Health is generated from reviewed registry records. Channel reach and evidence maturity remain separate so a built component cannot imply unsupported quality.

The reviewed snapshot contains 56 governed assets, including 51 components, with 211 of 218 required channel relationships implemented. It also reports only 11.3% of required evidence as current, 88 named gaps, and no Stable asset. That is deliberate honesty: implementation support is not the same as complete manual, visual, localisation, or channel evidence.

QZee One now acts as the shared operating layer behind the broader platform described in the QZee product case study. Its value is not only that it provides components. It gives designers, engineers, products, and AI a common way to understand what exists, what is safe to use, what still needs work, and who is responsible for the next decision.

04 · Craft

Decision trail

  • 01Make semantic intent the public contractSeparate core values, semantic roles, and domain-specific tokens. Products consume roles such as text, surface, status, and accent rather than reaching into raw colour ramps.
  • 02Share intent, not identical pixelsGenerate platform-native outputs for web and React Native, then define constrained email and marketing packages so each channel can express the same meaning appropriately.
  • 03Treat partner colour as an input, not a tokenAccept one third-party brand colour, then derive fill, pressed, boundary, soft, on-colour, and link roles against the active surfaces. Keep focus, status, and structure outside tenant control.
  • 04Give AI a machine-readable systemMake ownership, lifecycle, channels, evidence, gaps, and consumer topology queryable through reviewed registry data, generated JSON, and a deterministic read-only CLI.
  • 05Begin component submissions with the product problemRequire the proposer to show the existing contract considered, affected consumers, expected paths, acceptance evidence, and agent readiness before a shared asset is built.
  • 06Treat accessibility as a release propertyEnforce contrast, theme shape, raw-colour, interaction, structural axe, responsive, focus, and target-size rules in code while retaining named manual evidence for Stable promotion.
  • 07Migrate through fixed consumer contractsGive every active consumer one design-system check, install from its lockfile, verify package alignment, and track remaining adoption gaps without allowing arbitrary remote commands.
05 · Result

A governed system that makes reach and risk visible

QZee One now provides one governed contract across web, React Native, email, and marketing packages, with QZee One and Storybook serving people and a registry, generated health report, and CLI serving automated consumers.

The verified repository snapshot contains 56 governed assets, including 51 components, and records support for 211 of 218 required asset-channel relationships: 96.8% implementation parity. Every governed asset also has an agent-readable representation.

The health model deliberately does not equate implementation with maturity. At the same snapshot, only 11.3% of required evidence was current, 88 gaps had named severity and ownership, and no asset had yet been promoted to Stable. That transparency turns missing manual, visual, localisation, and channel evidence into visible work instead of an implied quality claim.

These are system coverage and governance outcomes, not claims that the design system alone produced QZee's commercial growth or that automated checks certify accessibility.

4,000+hardcoded values audited
56governed assets
94contrast pair gates
96.8%required channel parity
06 · Reflection

AI increased the need for governance, not the case for removing it

The most important AI decision was to make the system legible to software without pretending software should own design intent. A deterministic registry and read-only discovery layer reduced ambiguity; constrained task intake, early draft review, and release boundaries kept judgement accountable.

I also learned that a design system has at least two user experiences. People need examples, rationale, search, contribution support, and a visible health model. Agents need stable schemas, explicit allowed paths, deterministic commands, and unambiguous stop conditions. Both should resolve to the same source of truth.

Publishing incomplete evidence felt less flattering than a maturity score, but it was more useful. A system becomes trustworthy when it can distinguish built, supported, evidenced, and Stable rather than compressing them into one optimistic status.

Next case studyNagra Kudelski: cross-platform OTT experiences for OpenTV and Nagra Sports