SYSTEM DESIGN

FRONT-END DEVELOPMENT

Shifting the paradigm from canvas to codebase

A UX-led migration of OpenText's Design System into a repo-native, agentic authoring workflow.

  • Suggested insights
    Identify Figma source node

    Select Blueprint V1 component flagged for migration.

    Extract via figma-console MCP

    Pull raw node tree, bindings, and property definitions.

    Author JSON contract

    Capture anatomy, tokens, states, variants, and anomalies.

    Lint gate one

    verify_all.py validates node integrity against token dictionary.

    ksc-usecase-card.contract.json

    {

    "component": "ksc-usecase-card",

    "type": "component",

    "version": "1.2.0",

    "anatomy": {

    "root": "card-container",

    "elements": ["heading", "body", "cta"]

    },

    "boundVariables": {

    "cta.background": "var(--aurora-action-primary-background)",

    "cta.text": "var(--aurora-action-primary-text)",

    "body.spacing": "var(--space-md)"

    },

    "states": ["default", "hover", "focus"],

    "verified": true

    }

    Jira insights — migration pipeline
    Avg. ticket turnover

    Last 90 days

    Time from ticket open to merge.

    Basline

    4.2 days

    Current

    2.1 days

    Delta

    50%

    Weekly cycle time

    Baseline

    Post-Workflow

    W1

    W2

    W3

    W4

    W5

    W6

    W7

    W8

    verify_all.py - lint gate two

    #Card-useCase

    1 issue detected

    Status: Failed

    Rule violated

    Hardcoded value in slot bound to a semantic token in the dictionary.

    background: #FF6B35;

    background: var(--aurora-action-primary-background);

    ksc-usecase-card.module.css : line 24

Solution summary (TL;DR)

Solution summary (TL;DR)

OpenText's Blueprint V1 design system had reached an inflection point. What was once a flagship Figma library serving as a centralized source of truth for the brand's atomic makeup had steadily drifted due to its inability to scale at the pace of rapid development.

Necessary maintenance protocols such as auditing for redundancies, identifying informed use cases for net new patterns, and spec documentation fell into the hands of a UX team already operating at capacity upstream, resulting in a forced culture of ad-hoc updates and a steadily growing queue of undocumented conventions.

With the organization setting its sights on a revitalized Design System as a bi-product of a wider brand restructure in 2026, my role as Lead UX Designer of AI-Enabled Systems was collaborating with Front-End engineering teams to conceptualize and implement an agentic two-stage migration workflow that automated the transition from canvas to codebase.

Learn how we reduced Jira ticket turnover windows by approximately 50% with a code-first framework that positioned Storybook as our unified source of truth for extraction and scale, increasing determinism, eliminating rogue LLM interpretation, and enabling rapid refinement and scale.

State of the system

Blueprint V1 was born inside Figma at a time when the discipline of maintaining a canonical library required the maintenance itself to live inside the file. Every component our product surfaces referenced traced back to a master node, and every net-new pattern was authored, versioned, and documented in-canvas by the UX team. Compounding the drift, the underlying V1 Front-End rested on custom CSS with no utility foundation, no shared token dictionary, and no formal nomenclature to distinguish a component (a single reusable atomic unit) from a pattern (a compositional arrangement of several components serving a specific job). Designers and engineers applied the same term to structurally different constructs across working conversations, resulting in ambiguity that made system authoring harder to reason about and harder to scale in any consistent direction.

Audit existing patterns

Deprioritized

Review the current library for redundancies, discrepancies, and components that have drifted from production repo.

Direct to deployment

Active

Steps 1, 2, 3 and 5 are bypassed for launch compression. Components ship without preceding audits, iteration cycles, or post-deployment documentation.

Market research

Deprioritized

Evaluative market research, scaling proposed UI pattern against best-in-class conventions through Claude web search.

Direct to deployment

Active

Steps 1, 2, 3 and 5 are bypassed for launch compression. Components ship without preceding audits, iteration cycles, or post-deployment documentation.

Preliminary creative exploration

Reduced to ad-hoc

Explore, prototype, and refine proposed solutions against distilled audit findings.

Direct to deployment

Active

Steps 1, 2, 3 and 5 are bypassed for launch compression. Components ship without preceding audits, iteration cycles, or post-deployment documentation.

Dev deployment

Active

Approved patterns are built and migrated into the codebase as HTML / CSS files.

Undocumented conventions accommulate

Active

Ad-hoc updates replace structured maintenance. The delta between the system;s canonical version and its live implementation continuously widens.

Spec documentation

Deprioritized

Post-deployment documentation, owned by UX to capture anatomy, usage guardrails and variant property structure.

The UX team operated at capacity upstream. Maintenance protocols were known and defined but could not be sustained at the pace of development.

Audit existing patterns

Deprioritized

Review the current library for redundancies, discrepancies, and components that have drifted from production repo.

Market research

Deprioritized

Evaluative market research, scaling proposed UI pattern against best-in-class conventions through Claude web search.

Preliminary creative exploration

Reduced to ad-hoc

Explore, prototype, and refine proposed solutions against distilled audit findings.

Dev deployment

Active

Approved patterns are built and migrated into the codebase as HTML / CSS files.

Spec documentation

Deprioritized

Post-deployment documentation, owned by UX to capture anatomy, usage guardrails and variant property structure.

Market research

Deprioritized

Evaluative market research, scaling proposed UI pattern against best-in-class conventions through Claude web search.

Preliminary creative exploration

Reduced to ad-hoc

Explore, prototype, and refine proposed solutions against distilled audit findings.

Audit existing patterns

Deprioritized

Review the current library for redundancies, discrepancies, and components that have drifted from production repo.

Dev deployment

Active

Approved patterns are built and migrated into the codebase as HTML / CSS files.

Spec documentation

Deprioritized

Post-deployment documentation, owned by UX to capture anatomy, usage guardrails and variant property structure.

Direct to deployment

Active

Steps 1, 2, 3 and 5 are bypassed for launch compression. Components ship without preceding audits, iteration cycles, or post-deployment documentation.

Direct to deployment

Active

Ad-hoc updates replace structured maintenance. The delta between the system's canonical version and its live implementation widens continuously.

The UX team operated at capacity upstream. Maintenance protocols were known and defined but could not be sustained at the pace of development.

My mandate was to lead the UX team through the transition architecturally: identifying the workflow efficiencies that would smooth the transfer of authoring conventions from Figma into the codebase, and co-designing, in collaboration with Front-End engineering, the workflows that would allow designers to operate confidently inside a repo-native environment without being asked to adopt the traditional obligations of a software engineer.

Contracts before code: the migration workflow

Conventional practice, when converting a Figma component into code, is to prompt an LLM into interpretation of the source file. Interpretation is the layer where rogue LLM behaviour, hallucinated tokens, and hardcoded values are introduced, and no volume of prompt engineering adequately resolves what is fundamentally a structural problem. The migration workflow we architected removes the interpretation step altogether by inserting a machine-checkable intermediary between Figma and the React code that references it: a JSON contract, authored into token-dictionary/contracts/, that captures a component's real anatomy, its live token bindings, its property definitions, and any known anomalies in the source file. Every downstream step is verified against the contract rather than against an LLM's evolving memory of what the component should look like.

Figma source

Legacy Blueprint V1 component identified in the existing Figma library and flagged for migration into Storybook.

Extract source (transition)

Live extraction

Figma-console MCP, running via Figma's Desktop Bridge Plugin API, pulls the raw node tree, every boundVariables binding, and every componentPropertyDefinitions entry directly from the source file. Bypasses the pre-resolved output of the official Figma MCP to preserve raw evidence for verification.

Author against extraction (transition)

JSON contract authoring

Claude Code authors a structured contract into token-dictionary/contracts/, capturing the component's anatomy, live token bindings, states, real variants, and any known anomalies in the source.

Contract complete (gate)

Lint gate one

Verify_all.py runs a paired verification, validating the generated token CSS and the contract's internal integrity against the token dictionary before a single line of React is written.

Lint pass required (gate)

Component build

Claude Code, working directly in the repo, authors the React .tsx implementation and its scoped CSS module against the contract, alongside a matching Storybook stories file.

Render in browser (transition)

Browser render check

The built component renders in a live browser session and is compared, element by element, against a Figma screenshot of the same node captured through the figma-console MCP.

Parity confirmed (gate)

Lint gate two

Verify_all.py runs a second time, re-checking the finished component against its contract and its rendered output. Any deviation returns the component to Node 5 for correction.

Clean pass (gate)

Merge to Storybook

Clean-pass component merges into the shared Storybook library through GitHub, four files intact: contract, .tsx, CSS module, and stories file.

Correction loop

The pipeline moves through eight sequential steps: live extraction, contract authoring, first lint gate, component build in React and Storybook, browser render check against a Figma screenshot, second verification pass, correction loop for any deviation, and merge into Storybook. Extraction is executed through the figma-console MCP via Figma's Desktop Bridge Plugin API, deliberately bypassing the pre-resolved output of the official Figma MCP so that raw evidence remains available for downstream verification. The first lint gate runs verify_all.py, pairing two checks: one validating the generated token CSS, and one validating the component's markup against its own contract. Only a clean pass merges.

An end-to-end example makes the shape concrete. During the migration of #ksc-usecase-card, live extraction returned every real token binding from the source file, and the JSON contract was authored against that extraction. At the component build step, the LLM's initial React implementation introduced a hardcoded hex value on the card's primary call-to-action background; a slot where the contract had explicitly bound the value to var(--aurora-action-primary-background), a semantic token from the Aurora theme extension. The first lint gate fired immediately, flagging the raw hex against the rule that no hardcoded value is permitted in any slot where a semantic token already exists in the dictionary. The contract supplied the correct binding, the correction was mechanical rather than judgement-based, and the corrected build cleared the second verification pass, matched the Figma render, and merged. The linter caught the rogue LLM interpretation at the exact junction where it would otherwise have shipped as production code.

The pipeline moves through eight sequential steps: live extraction, contract authoring, first linCross-functional collaboration with Front-End engineering was concentrated at the output layer. Together, we finalized the four-file scaffold every migrated component now ships with: a JSON contract, a .tsx React implementation, a scoped CSS module, and a Storybook stories file. The scaffold ensures each component is optimized for Storybook hosting rather than delivered as an isolated HTML and CSS artifact, giving the migration a consistent target for every step in the pipeline to be measured against.

The code-first horizon: post mirgation workflow

The migration workflow is currently the daily driver. Once every Blueprint V1 component has moved through it, a second workflow takes over. Figma is no longer the default entry point for new work; it becomes a tertiary exploration surface, reserved for highly stateful patterns whose logic is more efficiently reasoned about visually, of which the navigation mega-menu is our present example. Everything else begins in the codebase.

Content brief

Content team delivers new material for a page or surface.

Pattern research config

Research

Best-in-class interaction pattern audit via Mobbin MCP, contextual to where the content will live, appended by existing insights from live pages via Microsoft Clarity.

Prompt drafting

Claude in repo

React component drafted directly against the codebase, lands in Storybook on a feature branch.

First draft review

UX audit

Design intent reviewed against the drafted component; iterations proposed if required by stakeholders.

Formalize spec docs

JSON contract

Contract authored or updated to reflect the finalized structure, lives inside the component folder as persistent reference.

Front-End handoff

Front-End fine-tune

Implementation polished in the same branch, contract-aligned.

QA gate

QA and staging

Component validated in staging before release.

Correction loop

For the sake of transparency, the flow illustrated below is prospective rather than reported: the post-migration workflow has not yet processed a real component end-to-end. When it does, the sequence follows a predictable arc. The Content team delivers new material for a page. Mobbin, accessed via MCP, is queried for best-in-class interaction pattern precedent contextual to where the content will sit. Microsoft Clarity is consulted against the outgoing page, and its real click, scroll, and attention data informs which elements warrant prioritization, compression, or elimination entirely. A standardized template prompt is then used to ask Claude, working directly in the repo, to draft a React component reflecting the intended treatment; the component lands in Storybook on a feature branch. UX audits the result, the corresponding JSON contract is authored or updated to reflect finalized structure, with Front-End engineering fine-tuning the implementation in the same branch before the component proceeds through QA, staging, and final production.

Notably, the JSON contract's role shifts between the two workflows. In the migration workflow, it operates as a precondition to code: authored and verified before any implementation exists. Post-migration, it lives inside each component's own folder and is kept in lockstep with every subsequent edit; a persistent, structured reference that an LLM session parses before touching an existing implementation, ensuring a fresh interpretation of the underlying code cannot reintroduce the rogue interpretation risk the project set out to eliminate.

Naming as architecture

The naming problem registered as the smaller of the two crises on paper and the larger in practice. Every component and pattern in V1 was named after what currently filled it rather than the job it performed. Bento was named after a visual layout metaphor. Three Pillar Narrative was named after a count that ceased to be accurate the moment a fourth pillar was added. Use Case Gateway Card was named as though it routed somewhere, when in practice it was a static proof grid with no navigation logic embedded. Appearance-based nomenclature offers designers almost no context for when to reach for a given component, and the name itself breaks the moment its content evolves

Research findings - naming convention audit
Anatomy of three published conventions

A competitive audit of Atlassian, IBM Carbon and Nord Design systems.

Prefix

Component

Modifier

State

Prop

Atlassian Design System

PascalCase Component + appearance prop

React Import

Button

Component

CSS Classs

aui

button

primary

React Import

appearance="primary"

appearance="subtle"

appearance="link"

appearance="warning"

IBM Carbon

PascalCase Component + kind prop

React Import

Button

Component

Compound

primary

Modifier

button

Base noun

CSS Class

cds

btn

primary

Variants

kind="primary"

kind="secondary"

kind="tertiary"

kind="ghost"

kind="warning"

Nord Health

Three-prefix system

Web Component

nord

Prefix

Button

Component

Modifier Class

.n

Prefix

button

Base noun

primary

Modifier

State Class

.is

State Prefix

loading

Status

React Import

kind="primary"

kind="secondary"

kind="tertiary"

kind="ghost"

kind="warning"

State (hover, focus, disabled, active, loading) is a switch on the component, expressed through props or a dedicated state class. Component state is never encoded into the component name.

Research into three published Design Systems informed the resolution. I studied Atlassian, IBM Carbon, and Nord Health directly; examining their live Figma libraries and their published documentation rather than deferring to secondhand summaries. Atlassian's convention follows [Modifier] [Base Noun], with every meaningfully different component receiving its own dedicated name. IBM Carbon's shipped code adopts [Modifier][BaseNoun], favouring a single component with built-in options wherever variance is cosmetic rather than structural. Nord Health applies {prefix}-{name}, with modifiers applied through a separate class and states granted their own distinct prefix altogether. Convergence occurred on one absolute rule across all three systems: state, whether hover, focus, disabled, active, or loading, is a switch on the component and is never encoded into the name.

Keystone's grammar, adopted for the new system's component library, is #ksc or #ksp followed by the modifier, followed by the base noun. #ksc denotes a component; #ksp denotes a pattern. The modifier is the role or job that distinguishes a given variant from its siblings. The base noun is what the object fundamentally is, and it survives a full content swap without requiring rename. Underpinning the grammar is the three-layer token architecture that grants semantic names their real values: a Tailwind foundation of 407 variables at the base, a Themes semantic layer of 333 variables aliasing those foundation values, and per-sub-brand theme extensions (Aurora, OT Digital, and Cyber Security) that inherit the Themes collection and store only what they actually override.

Original nomenclature
#Card-useCase

#Card-useCase

#Three-pillar

#Three-pillar

#Compare

#Compare

Revised nomenclature
#ksc-usecase-card

#ksc-usecase-card

#ksp-narrative-pillars

#ksp-narrative-pillars

#ksp-catpositioning-argument

#ksp-catpositioning-argument

What's next?

Once every Blueprint V1 component has passed through the migration pipeline, our team will stress-test the code-first workflow against real net-new components; refining standardized prompts, audit gates, and the contracts as the system scales in tandem. In the interim, the workflow's approximately 50% reduction in Jira ticket turnover has already had a knock-on effect through the lens of designers being afforded the time to move upstream into more exploratory work; enabling a dual-agile cadence where the pipeline operates deterministically in one lane, and the team investigates net-new design challenges alongside it.