We solved the product first, then turned the solution into a system
NXTThing began as a zero-to-one platform with no library, no patterns and no screens. I let real workflows shape the product before formalising them into a design system that now holds 120+ screens together, and carried the product through a company rebrand.

There was nothing to start from.
Most design system stories begin in the middle: a product exists, it has drifted, and a designer arrives to bring it back into line. That wasn’t this. When I joined NXTThing RPO as the only designer, there was a set of business requirements, recruiter knowledge held in people’s heads, a Whimsical file and a handful of early screens.
No component library. No tokens. No type scale. No patterns, because nothing had yet happened twice. Eight engineers, two project managers, several time zones, and a platform that would grow to nine modules and 120+ responsive screens.
Token architecture
Six variable collections in a layered chain, from raw colour through meaning to the jobs components ask for.
Component library
Rules that answer hundreds of combinations instead of drawings of each one, aligned to Material UI.
Documentation
Anatomy, states, token bindings and edge cases, so the system kept working when I wasn’t awake to explain it.
We were paying for the same decision more than once.
By the time eight modules were live or in progress, repetition stopped being cosmetic and started costing us. The product didn’t look untidy. The same decisions were being made, and paid for, again and again.
Responsive behaviour redefined screen by screen
Small changes needing updates across many designs
Engineers asking questions only I could answer
Patterns living in Figma that never reached production

The reasoning behind the order“In a zero-to-one product, a system built on behaviour that is still moving doesn’t stabilise anything. It hardens the wrong answers and makes them expensive to undo.”
Build it so a change only has to happen once.
I gave myself one requirement to design against: when something changes, it should change in one place and travel. So colour became a chain of three layers, each taking a decision away from the one above it, with a fourth collection handling scale and rhythm alongside them.
Brand tokens→Alias tokens→Mapped tokens→Components

A shared language
A button no longer asks for blue. It asks for primary, and everyone agrees what primary means.
Rules, not drawings
Components are defined as matrices, so new combinations are answered rather than designed.
Reviews about states
Design and engineering named things the same way, so reviews moved from looks to missing edge cases.
Four layers, each with one job.
Every layer points one step down. Nothing a component touches holds a raw value.
Brand tokens
Raw source-of-truth values: full colour scales from 50 to 900, with Light, Main and Dark named inside them. Never applied to a screen; they exist to be referenced.

Alias tokens
Brand colours mapped to product meaning: Primary, Secondary, Success, Information, Warning, Error. The palette can evolve without touching a component.

Mapped tokens
The only layer components consume, grouped as Text, Surface, Border and Icon. Thirty-six decisions answer for every component in a nine-module platform.

The responsive layer
Typography, spacing, sizing and layout behaviour for every breakpoint, centralised the same way colour is instead of overridden screen by screen.

One system, two brand generations, every screen held together.
The architecture was built for a product still finding its shape, then proved itself when NXT became Personegy and the system absorbed the change instead of being rebuilt.
Brand, Alias, Mapped and Responsive, across two brand generations
529 in the current Personegy system, 327 carried from NXT V1
Across nine modules, from 375px to 1920px
NXT’s early product language, then Personegy V2
The platform was built by sixteen people over roughly eighteen months. The architecture, tokens, component definitions and documentation were mine; engineering built the implementation it aligns to. The variable counts are real and readable in the file.
- Before
- Responsive behaviour redefined screen by screen
- After
- One responsive collection every screen reads from
- Before
- Answers that only existed with the designer
- After
- Documented states, edge cases and token bindings
- Before
- A rebrand would mean opening 120+ screens by hand
- After
- One layer changed, and everything above it followed
So, how did we get here?
From the system that shipped, to why it was built in this order.
I started by looking backwards.
Before designing anything new, I went back through everything the product had already produced: near-duplicate colour values, filters behaving differently across modules, Material UI components customised more than one way, patterns that lived in Figma but never reached production. Everything recurring went into one of three buckets.
Familiar and ready
Useful and implementation-ready: the core table row, status chips, the primary action.
Right idea, loose rules
A valid purpose with inconsistent anatomy or states: filter panels, form controls, modals, empty states.
One-offs
Duplicates of something we had, or patterns that couldn’t scale past the module they were born in.

Six questions that shaped the system.
Each started with more than one reasonable answer.
When should a zero-to-one product build its design system?
- Context
- No system to inherit and no patterns to extend. The real question was whether we were designing the right workflows.
- Alternative
- Start with colour, type and components on day one, like most design system stories.
- Decision
- Functionality first. Reuse patterns informally while the product moved, and formalise only once eight modules showed the same decisions repeating.
Colour as values, or colour as meaning?
Aliases map brand colours to product meaning, and those meanings are written down: Primary covers buttons, links, active navigation and interactive states; Success positive status; Warning caution and pending; Error validation and failures. A semantic layer only works if everyone agrees what the words mean.
The shift“A button no longer asks for blue. It asks for primary.”
Draw every button, or define the rules?
Three variants, three sizes, six semantic purposes, five interaction states, and an optional icon at the start, the end, both or neither. I never drew those combinations. I defined rules that answer hundreds of intersections, which changed the team’s question from “what should this button look like here?” to “which configuration fits this action?”

One fixed table, or a structure every module can bend?
Recruiting in practice is mostly scanning, so the table took more of my time than anything else: selection, sorting, filtering, pagination, row and bulk actions, status, loading and empty states, and column priority that changed with the screen. I made it a shared structure each module could bend, and wrote the edge cases into the definition.
- 01
Content runs long
Truncation and wrapping rules per column type.
- 02
Data is missing
Defined empty cells instead of improvised dashes.
- 03
A request fails
Error and retry states inside the table, not around it.
- 04
Someone lacks permission
What hides, what disables, and what explains itself.

Review accessibility at the end, or write it into the component?
Recruiters live inside this product all day, so accessibility became part of each component’s definition: fix contrast in one component and it’s fixed everywhere it appears. WCAG 2.1 AA shaped contrast, focus order and visible focus, and status was never carried by colour alone. A label, an icon or a position always reinforced it.

A self-contained Figma library, or the thing that actually ships?
The frontend was React and Material UI. Instead of handing engineering a fictional component universe to translate, I aligned the component model with Material UI primitives and customised hierarchy, states and density for NXT’s workflows. Design and engineering named the same thing the same way.

Then the company rebranded.
NXT became Personegy: new brand foundations, a refreshed identity, and a second version of the product to carry it. If colour had been applied directly to components, this would have meant opening 120+ screens by hand with the near-certainty of missing some.
- Changed
- The brand layer, with Personegy’s new foundations
- Unchanged
- Alias names and their meanings
- Result
- Every component still asked for Palette/Primary/Main and still got the right answer
Both generations are still visible in the file: NXT collections of 173 and 154 variables beside Personegy’s 212, 212, 36 and 69. Version 2 also brought refined collections, improved variants and breakpoint-specific behaviour, all still aligned with Material UI and React.

The system, working inside Personegy.
Connect, Sourcing, Scheduling, Hires and Analytics reuse the same shell, tables, filters, chips, states and action hierarchy. What recruiters learn in one module transfers everywhere else.



What I’d tell the next designer
The order we worked in is the thing I’d defend hardest, and the thing most likely to be questioned. A design system separated from the product that gives it meaning is just a library of opinions.
- 01
Let repetition earn the rules.
The product showed me which decisions kept repeating. Repetition made them patterns, stability made patterns components, and only then did tokens have anything worth binding.
- 02
Match the order to the evidence.
Joining a product that already exists? Start from the system, you have the evidence. At genuine zero you don’t, and early rules become decisions nobody needed.
- 03
Organise complexity, don’t hide it.
Recruiting at volume is complex. The system’s job was to turn that into decisions a distributed team could understand, reuse and maintain.
The product gave the design system its purpose. The design system gave the product room to grow.