Selected work03 / 03  —  GiG · Design systems

Case study / B2B ecosystem

Backoffice Design System

Building one product language across a complex ecosystem.

The Backoffice library's original light and dark colour scales, open in Figma
One colour vocabulary, across light and dark. The original library in Figma.

One colour vocabulary, across light and dark. The original library in Figma.

The Backoffice library's original light and dark colour scales, open in FigmaOpen original-size capture

From 2021 to 2025, I built and maintained the Figma system behind five GiG backoffice products. The challenge was not to make every screen identical, but to give different teams a dependable shared language for real production work.

Period
2021–2025
Role
Junior to Senior Product Designer
Scope
System architecture, components, variables, governance, design-to-code alignment, cross-team workshops
With
Design, Product and Engineering across the backoffice ecosystem
The problem
Five backoffice products needed consistent foundations without losing their specialist workflows.
My contribution
Reconstruct the code-based UI kit in Figma, run the shared library and its rules, and connect five teams that rarely talked to each other.
The change
A shared design source for Core, CoreX, Magic, LogicX and GiG Trader, used by around seven designers and more than twenty developers.
The case in briefWatch the overview0:49

Backoffice Design System in 49 seconds

The case in brief: what the library was, where it started, how it was built from atoms to templates, colours named by their job, how a component got in, the bridge between five teams, and the 2.0 it was heading to. Music, no narration.

Start with what was already shipping.

When I joined GiG in 2021, the backoffice already had a code-based UI kit built on Bootstrap 4.6. Figma had only a small library. Designers needed a reliable source that reflected what Engineering could actually build.

I reconstructed the existing kit in Figma, then developed components as product needs emerged. Controls, tables, navigation, forms and states had to capture behaviour as well as appearance. This was a working production library, not a speculative redesign.

An early library page: the Heading 5 + Card Group | Quick Link pattern composed for desktop, tablet and mobile
From the original library: one quick-link pattern, composed for desktop, tablet and mobile.

From the original library: one quick-link pattern, composed for desktop, tablet and mobile.

An early library page: the Heading 5 + Card Group | Quick Link pattern composed for desktop, tablet and mobileOpen original-size capture

Consistency without sameness.

Core, CoreX, Magic, LogicX and GiG Trader shared the library, but not the same workflows. Account operations, content management, rule building and trading each needed their own interaction patterns.

I used atomic design to organise the system from foundations to complete patterns. The important decision was where reuse stopped: share the familiar building blocks, but preserve specialist behaviour when a product genuinely needs it.

Shared foundationsBackoffice library
Core
Account operations
CoreX
Platform operations
Magic
Content management
LogicX
Rules & automation
GiG Trader
Trading workflows
  • Foundations — typography, colour, spacing and states
  • Shared patterns — fields, tables, navigation and overlays
  • Product-specific patterns — specialist behaviour, not arbitrary variation
The payment-method table with only one status cell highlighted: a badge cell from the Table Cell atom

Atom / Table Cell One cell type, here a status badge. A single set of 54 variants covers every cell the tables need.

The payment-method table with only the status column highlighted: heading, filter dropdown and badge cells

Molecule / Table Column A heading and its filter over a stack of cells of one type.

The full payment-method table organism, with placeholder text and badges in every column

Organism / Payment Method table Columns assembled into one table, still holding placeholder content.

The payment-method table template filled with real content: Visa, MasterCard, PayPal and other methods with provider, currency, type and enabled or disabled status

Template / Magic payment methods The same table with Magic’s real content: providers, currencies, types and status.

One table from Magic, from a single cell to a filled template. Captures from the library file.

Atom / Table Cell

The payment-method table with only one status cell highlighted: a badge cell from the Table Cell atomOpen original-size capture

Used by two or more products? Make it shared.Working rule from the library guidelines

A small rule with a large consequence.

The library guidelines made the boundary explicit: when two or more products needed the same pattern, with the same behaviour, it belonged to the shared ‘All’ variant. Product-specific variants stayed available when behaviour genuinely differed.

Requests came from designers, product owners and front-end leads, usually in the middle of product work. Each one went through the same checks before anything was drawn: does something already do this, how many products would use it, what would change for the screens already built on the old version, and could Engineering build it from the existing UI kit. Most requests ended as a new variant or property of an existing component; a few became new components.

Exceptions were allowed, but named, so they stayed visible until they could be retired.

The contribution rule

One product keeps it. A second moves it to All.

Which products use each component, and where it lives in the library
ComponentPlatformMagicLogicLibrary variant
Card | Payment MethodNot usedUsedUsedAll
Card | RulesNot usedNot usedUsedLogic
Modal | ConfirmationUsedNot usedUsedAll
Card | SEO EntryNot usedUsedNot usedMagic
Component names from the library; which product uses which is illustrative. The branch is the file’s own Product variant: Platform, Magic, Logic or All.

From request to release

The same four questions, every time.

  1. 01Does it already exist?

    Search the library first.

  2. 02Who else needs it?

    Two or more products: it goes to All.

  3. 03What would it change?

    Check the screens built on the current version.

  4. 04Can the code support it?

    Confirm with the front-end lead.

Three possible answers

  • Extend

    A variant or property on an existing component.

    Most requests
  • Share

    A new component in All, for every product.

  • Keep local

    A new component in one product, until a second needs it.

Whatever the answer, it shipped the same way: built, documented, logged in the changelog and announced to the teams using it.

One exception, end to end

Allowed, but named.

  1. 01 · Request

    “We need the old and the new shadows side by side while we migrate.”

    Old and new shadows, side by side

    CoreX’s product owner and front-end lead needed both styles while they migrated. The product was still called Endeavour.

  2. 02 · Decision

    Atom Extended shadows (Endeavour)Temporary

    A named, temporary atom

    Not a quiet one-off in their files: an atom in the library, labelled with the team that needed it.

  3. 03 · Release

    Added Atom: Extended shadows (Endeavour)Changed Atom: Shadow, new default colour

    Logged where everyone looks

    Shipped with a changelog entry, so every team could see the exception and that it was meant to go.

The atom’s name and the changelog lines are the library’s own.

Separate colour from its job.

The same split between what is shared and what is specific applied to the foundations, starting with colour. As Figma’s capabilities evolved, I moved colour towards a primitive-to-semantic variable architecture. A component could reference what a colour does—surface, text or feedback—instead of a fixed value.

The file contains 184 primitive colours and 84 semantic variables, each with a light and a dark value. Those foundations let the interface change appearance without changing its underlying structure.

Primitive colours
184
Semantic variables
84
Modes, light and dark
2

One value, followed into a product

Where a colour decision actually ends up.

  1. 01 · Primitive
    A value.

    #1AD66E is one step of the green scale: a colour, with no meaning yet.

  2. 02 · Semantic
    A role.

    The semantic variable success gives it a job: positive actions, badges and callouts. In dark mode the same role resolves to #4BD78A.

  3. 03 · Code
    /* handed to Engineering */
    --color-success
    --color-success-accent
    --color-success-soft
    A shared name.

    The role reached Engineering under the same name, as a CSS custom property, with its accent and soft companions beside it.

  4. 04 · Component
    The library's Success callout: a check icon and text in green on a pale green ground
    A component.

    The Success callout uses the role for its icon and text, on the softer success-soft ground.

  5. 05 · Product
    Magic payment-method rows with green Enabled and red Disabled status badges
    A product.

    In Magic’s payment methods, the Enabled badge carries the same value.

The primitive and semantic steps are set from the library’s values, the code step from the CSS variable list handed to Engineering; the callout and the badge are crops of original captures. The badge’s colour was checked against #1AD66E on the capture itself.
LogicX rule editor in dark mode with version history openThe same LogicX rule editor in light mode
The same roles at full-screen scale: LogicX’s rule editor in light and dark. Original Figma captures; drag the control to compare.

The destination was production, not Figma.

The components represented shipped work: they either came from the existing UI kit or were created for something a product needed. The system became a shared design source across five backoffice products, with common patterns and room for specialised workflows.

Around seven designers, more than twenty developers and three or four product owners worked from it. That audience shaped the documentation: designers needed the rules, developers needed names and states they could map to code, and product owners needed to see what already existed before asking for something new.

  1. 01Navigation
  2. 02Page actions
  3. 03Filters
  4. 04Status
Magic payment-method management: sidebar navigation, an Options action, column filters and a table of methods with Enabled and Disabled status badges
Magic, two workflows: payment methods and missions. Different data and actions, the same navigation, page actions, filters and status badges from the shared library.

Magic / Payment methods

Magic payment-method management: sidebar navigation, an Options action, column filters and a table of methods with Enabled and Disabled status badgesOpen original-size capture

A library built through product work.

Scale of the Figma library, recorded in a file audit.

5,242
components
organised into 323 component sets
77,347
instances
reused throughout the file
281
variables
including 84 semantic variables, in light and dark

The bridge between five teams.

Keeping five products on one library was as much about people as about files. I ran it like a product, with numbered releases and code as the reference, but the harder part sat between the teams.

We shared the Figma library, but not the code. Four products still built on the old Bootstrap 4.6 UI kit, while CoreX had written its own React library with custom CSS, based on the design system. Working on all five products gave me a view no single team had: the teams worked in silos and rarely knew what the others were building, so I became the connection. I knew who to ask, pointed teams to work that already existed and, when it mattered, put them in the same room.

I organised workshops where the teams compared how they built their front ends. CoreX’s library was the most modern and the closest to the system, so the teams agreed to migrate the old UI kit to it step by step, and the 2.0 was planned around it.

Between the teams

From five silos to one shared base.

  1. 1One Figma library, but four teams on the old Bootstrap kit and CoreX on its own React library.
  2. 2Working on all five, I knew who to ask and who to connect.
  3. 3Workshops: CoreX’s library became the shared base, with the old kit migrating to it.

NextStarted in 2025, not shippedDashed marks what was planned

Version 2.0: for people and AI tools.

The workshops settled where the code would go. The Figma library needed its own rebuild: by 2025 it showed its age. It was built before component properties and variable modes matured, so its components had grown by multiplication: the Input alone had 98 variants.

The 2.0 had two aims: a leaner library for designers, and one that AI tools could read as reliably as people. That meant properties instead of variant combinations, names that say what a token or component is for, a description and usage notes on every component, and a direct link to the coded components the teams had agreed to share.

I used AI tools for the repetitive part, rebuilding components and drafting their documentation, and reviewed every result by hand. When an agent merged the Button’s Hovered and Pressed states because their fills matched, I kept them apart: code treats them as different interactions, and some categories change the label when pressed. The core components reached their 2.0 version; the work stopped before it was rolled out to the products.

Input, 1.x to 2.0

Same input, a seventh of the variants.

1.x · Shipped

98 variants

2 surfaces × 7 types × 7 states

Open the real 1.x Input set
  1. ÷ 2Surfacebecomes a variable mode: the input reads its ground from the page or the widget
  2. ÷ 3.5Seven typesbecomes two kinds and four booleans

2.0 · Reconstructed approach

14 variants

2 kinds × 7 states, plus properties

  • + Leading icon · boolean
  • + Suffix text · boolean
  • + Clear button · boolean
  • + Icon group · boolean
  • + Surface · variable mode
Left: the real 1.x Input set, drawn as one small schematic per variant. Right: what the 2.0 approach yields for the same input, reconstructed because the 2.0 file is not available. State stays a variant because it maps to real interaction states in code.

The plan for 2.0

One source, read by people, code and AI tools.

StartedCoreX’s React library

Agreed in the workshops as the shared base.

Library 2.0

  • StartedComponents on properties

    Properties instead of one variant per combination.

  • StartedDescriptions and usage notes

    On every component, drafted with AI, reviewed by hand.

  • PlannedNames that say what they are for

    Tokens and properties a tool can read.

Planned connections

  • Code ConnectCoded UI Kit

    Each component linked to its coded twin.

  • MCPAI tools

    Structured docs an assistant can read.

  • DocsDesigners and developers

    Component, rules and code in one place.

Solid: decided or started. Dashed: planned, not built. Code Connect links a Figma component to its coded twin; MCP lets an AI assistant read the library directly. The work stopped before any of these connections were made.

Judge a system by the decisions it makes easier.

Not by how many components it contains. The parts of this work I would repeat are the small rules that saved arguments, the exceptions that stayed visible, and the conversations between teams that nobody else was set up to start.

The shipped library carried four years of real production, and the limits of the Figma it was built in. The 2.0 was meant to answer those limits; it was never rolled out.

Consistency is not making everything the same. It is giving different products the same rules.