Selected work
Case study / The Brief AI

The Brief Design System: re-architecting the foundation

The MUI-based design system I built for Ad Studio, which then became the design language for redesigning the whole Creatopy platform. A three-layer token architecture and a full component library, built to code with engineering in Storybook.

Role
Senior Product Designer, system owner
Partners
Engineering (component build in Storybook)
Company
The Brief AI (formerly Creatopy)
Scope
Token architecture, component library, type system, design-to-code parity, platform rollout
The full system on one board: atoms, molecules and organisms laid out together with the foundations and component library⤢ Click to zoom
The whole system on one board, from atoms up to organisms. Click to zoom in and pan across it.
01

Why rebuild it

The platform had outgrown its original system. As it shifted toward AI-native workflows and an increasingly complex editor, the old library couldn't keep pace: inconsistent components, values that drifted between design and code, and no clean foundation to build new surfaces on.

The decision wasn't to patch it. It was to re-architect the whole thing on a new MUI foundation, so the system could scale with the product instead of fighting it. That meant rethinking the structure from the tokens up, not just refreshing the surface.

It started with one product. Ad Studio was the first surface built on the new system, the proving ground for the tokens, the components and the engineering workflow. Once it held up there, the same system became the design language for redesigning the rest of the platform. See Ad Studio, the product it first shipped in →

02

The architecture

The core of the system is a three-layer token model, each layer building on the one beneath it. Primitives define the raw palette and scales; a semantic layer maps those primitives onto meaning; and components consume only the semantic layer, so the rest of the system never references a raw hex or pixel value directly. It references intent.

Layer 1Primitives
The raw scale. Grey/Grey 900 · radius steps · the type ramp. Values with no opinion about where they're used.
↓ aliased to meaning ↓
Layer 2Semantic tokens
Text/Primary · Text/Secondary · Action/Hover · Action/Selected · Other/Divider · Accent/Main. Named for intent, not appearance.
↓ consumed by ↓
Layer 3Components
Atoms and assemblies that only ever reference semantic tokens, so one change at the foundation cascades everywhere, predictably.

This is the whole point of the structure: because components reference semantic tokens and semantic tokens reference primitives, a single change at the bottom flows through the entire system without hunting through files. Rename the intent, not a thousand hex values.

Text/Primary
#212121
Text/Secondary
#666666
Text/Disabled
#9E9E9E
Accent/Main
#005BE5
Action/Selected
#F2F7FE
Action/Hover
#EBEBEB
Other/Divider
#F1F1F1
Action/Active
#757575
Warning/Main
#C39634
Warning/Alert/Bg
#F3E7CE

Real tokens from the system. Note the naming: intent first (Action, Text, Warning), never the colour. Even alerts get their own semantic sub-group.

03

How it composes: atoms, molecules, and a full element matrix

The system is built to compose. Atoms are the smallest sanctioned pieces: a label, a select, a text field, a toggle, an icon button, a colour control. Molecules assemble those atoms into the functional rows of the editor's properties bar. Nothing in a molecule introduces a new value; it only arranges atoms that already exist.

AtomsSanctioned smallest pieces
Label · select · text field · toggle · checkbox · icon button · colour palette · slider · alignment controls.
↓ assembled into ↓
MoleculesProperty-bar rows
Functional groupings built only from existing atoms. No new values, just a careful arrangement.
↓ resolved across every element type ↓
MatrixElement type × property
Text · Button · Image · Shape · Illustration · Logo · Line · Audio · Mask · Video · Countdown, each mapped to the property bar it needs.

The hardest part wasn't any single component. It was the combinatorial problem underneath: the editor supports many element types, each with a different set of editable properties. A text layer, a video, a countdown and a particle effect don't expose the same controls.

So I mapped the whole space as a matrix: every element type against every property, with the correct property bar resolved for each combination, all from the same atoms and molecules. That's what keeps the editor coherent no matter what the user selects, and it's the structure that makes adding the next element type a known, bounded task instead of a redesign.

The element-type × property matrix: every element type across the top, every property down the side, with the resolved property bar for each combination⤢ Click to zoom
The element-type × property matrix: every element type against every property, resolved from the same atoms and molecules. Click to zoom in and pan across it.
Anatomy of the Button element: its property bar annotated and broken into property groups (Basic actions, Layer, Label, Background, Actions)⤢ Click to zoom
Zooming into one element: the Button property bar broken into its groups (Layer, Label, Background, Actions). Each group is molecules assembled from existing atoms. Click to zoom in.
The molecules page: property-bar rows, each one assembled entirely from existing atoms⤢ Click to zoom
Molecules: the property-bar rows, each built only from existing atoms. Click to zoom in and read across them.
04

The type system

One family, worked hard. Inter carries the whole UI, every step a named, defined token with a fixed size, weight, line-height and letter-spacing, so type is applied by role rather than eyeballed per screen.

Overline
Inter · 600
Overline label, 12 / 28
Body 3
Inter · 400
Body copy at 12 / 18, the platform's reading size.
Input Text
Inter · 500
Field input, 11 / 24

Real type tokens. Roles, not one-off sizes, so the ramp stays consistent across every surface.

05

Governance: what's in the system, and what isn't

A system is only as strong as its boundaries. On the atoms page I split every element into “components used” versus “variants or ideas only.” Sanctioned atoms on one side, exploratory work clearly fenced off on the other.

That line matters more than it looks. It tells anyone opening the file exactly what's safe to build with and what's still thinking-out-loud, which is what stops a system from quietly sprawling into a dozen near-duplicate buttons.

The atoms page, split into “components used” versus “variants or ideas only” so the sanctioned set is fenced off from exploration⤢ Click to zoom
The atoms page: sanctioned “components used” on one side, “variants or ideas only” on the other. Click to zoom in.
06

Key decisions

D1

Build on MUI, not from scratch

I based the system on Material UI rather than inventing every primitive. MUI gave a battle-tested foundation and a structure engineering already understood, so the team could move faster and lean on a known accessibility baseline.

TradeoffLess total freedom than a fully bespoke system, in exchange for speed, a shared vocabulary with engineering, and far less reinventing of solved problems.
D2

Layered tokens, not flat references

I split tokens across primitives, a semantic layer, and the components that consume them, rather than letting anything reference raw values directly. It's more upfront structure, but it's what makes the system maintainable at scale.

TradeoffMore indirection to set up and explain, in exchange for changes that cascade predictably and a system that bends without breaking.
D3

Govern by drawing a hard line

I made the sanctioned-versus-exploratory split explicit in the file itself, rather than keeping it in my head. Governance you can see is governance the rest of the team can actually follow.

TradeoffThe discipline of maintaining that boundary, in exchange for a system that stays coherent instead of sprawling into duplicates.
07

Design-to-code parity

A system that only lives in Figma is half a system. I worked directly with engineering to build the components in Storybook, the full set: inputs, buttons, selects and the rest, so the design source of truth and the coded source of truth were the same thing, not two drawings of it.

The shared MUI base and the semantic token layer are what made that parity practical: when design and code speak the same structural language, handoff stops being a translation exercise and the gap where drift creeps in mostly closes.

We proved the whole pipeline in Ad Studio first, design tokens to Figma components to Storybook to shipped UI, then rolled the same components out as the platform was redesigned around them.

The CDSButton component: its full variant set in Figma on the left, the same component built in Storybook on the right⤢ Click to zoom
Design-to-code parity: the CDSButton variant set in Figma, beside the same component built in Storybook. Click to zoom in.
08

Outcome

  • From one product to the whole platform. Proven in Ad Studio, then adopted as the design language for redesigning the rest of the Creatopy platform.
  • A scalable foundation the platform's newer AI-native surfaces are built on, instead of a library actively slowing the work down.
  • Predictable change. The two-layer token model means a foundational update flows through the whole system without manual hunting.
  • Tighter handoff. Storybook parity and a shared MUI vocabulary cut the translation work between design and engineering.
  • A coherent system, not a sprawl, held together by an explicit line between what is sanctioned and what is exploratory.
09

Reflection

A design system isn't a library of components. It's a set of decisions about how decisions get made, and the real work is the architecture underneath, not the screens on top.