Deep dive Design System Figma → Vue.js WCAG 2.2 AA 2 plugins built (vibe-coded)

A 250+ component design system, built from zero, with two custom plugins keeping it honest.

I lead the architecture, governance and tooling of the design system behind HikeOn's custom eCommerce ERP, built for a US foodservice and packaging brand with a 30,000-SKU catalog.

Role
Design Systems Lead
+ AI Product Design Lead
Team
4-member design team
Daily sync with eng architects
Timeline
Oct 2024 to present
Built from zero
Scale
250+ components · multi-mode
Figma → Vue.js · web + mobile
01 · What I walked into

No shared system. Designers improvised. Engineers rebuilt the same components per module.

Before writing a token spec, I ran an audit. I catalogued every component in the product files, read the front-end code alongside them, and sat with engineers through a real handoff to see where intent got lost. Each finding became a goal I signed off with engineering.

FindingGoal
No canonical componentOne source of truth that maps directly to Vue.js components.
Tokens defined twiceOne token architecture, shared by Figma and code, for theming, dark mode, density and white-label brands.
Intent lost at handoffThe Figma component becomes the spec, so discrepancies surface before QA.
Invisible driftAdoption and design debt measured every week.
Ungoverned contributionA contribution model for designers outside the core team (section 05).
Accessibility (my addition)WCAG 2.2 AA from day one.
PHASE 1

Audit & alignment

PHASE 2

Token foundation

PHASE 3

Primitives & first composites

PHASE 4

Pipeline & handoff protocol

PHASE 5

Governance & tooling

ONGOING

Weekly measurement

02 · Figma architecture

Library structure.

The system is four publishable Figma libraries. Each one depends only on the layer beneath it, so dependencies run in one direction and never sideways.

Four-layer library dependency diagram
LibraryHolds
01_TokensColour, spacing, type, radius, elevation and motion variables. No components.
02_PrimitivesIcons, avatars, badges, dividers, base inputs. Consume tokens only.
03_ComponentsButtons, form fields, data tables, navigation, modals, charts, AI interaction patterns.
04_PatternsEmpty states, error states, AI confidence states, copilot panels, multi-step forms.

Token architecture.

The library graph controls what is allowed to depend on what. The token layers control how a value resolves. A brand change moves through the token layers without touching the library graph at all.

Tokens use three layers. Primitives hold raw values, semantic tokens describe intent, and component tokens map intent to a specific UI role.

LayerExample & rule
PrimitiveRaw values in the Colors collection (Colors:Grey/Grey-1200, Colors:brand/color-brand-900-brand, Colors:white/Color-white-1000, Colors:Pallet/Pallet-01-default). Designers never reference these in components.
SemanticTEXT/text-default → Grey/Grey-1200 (Light) / white/Color-white-100 (Dark) · BACKGROUND/bg-page-primary → white/Color-white-1000 (Light) / Grey/Grey-1200 (Dark). Describes intent. Resolves per mode.
ComponentBUTTON/bg-button-primary → brand/color-brand-900-brand · ICON/icon-active → brand/color-brand-900-brand (Light) / brand/color-brand-1500 (Dark). Maps semantic intent to a specific UI role.

Every colour pairing in the semantic set is pre-checked against WCAG 2.2 AA, with APCA for the borderline calls. A failing pair doesn't exist in the set, so a designer can't reach for one by accident.

Modes.

The semantic and component layers live in one collection, Global_combinations, which resolves across Light and Dark. Component tokens alias semantic tokens, and semantic tokens alias each other, so ICON/icon-success and BORDER/border-input-selected both resolve through ICON/icon-active. The same collection exports to engineering as token JSON consumed by the Vue.js build, so a mode switch in Figma and a mode switch in code use the same names.

Here are six tokens from the charts palette with their real values straight from the collection. One semantic name resolving to two tints:

Royal Blue
Light
#e9eeff
Dark
#09143a
Green
Light
#f2ffe4
Dark
#29430c
Yellow
Light
#ffffe4
Dark
#4b3d04
Red · Danger
Light
#feeae9
Dark
#3f1515
Purple
Light
#f8f2ff
Dark
#2f1e42
Grey Font
Light
#434d56
Dark
#a3afb9
Four-layer library dependency diagram

Naming conventions.

Naming is the contract between design and code. It was locked on day one and hasn't changed since.

ElementRule
TokensGROUP / role-element-variant, grouped by intent (TEXT, BACKGROUND, BORDER, BUTTON, ICON, ALERT, Status), kebab-case roles. e.g. BUTTON/bg-button-primary, TEXT/text-placeholder-muted, BORDER/border-input-selected
ComponentsPascal-case in Figma matches Pascal-case in Vue. Button / DataTable / FormField. Variant property names match on both sides.
VariantsStandard set across every component: Size · Variant · State · Density. Always in that order. No component invents a new axis without review.
SlotsComponent properties named after Vue slots: leading, trailing, content. One-to-one map to engineering.
Four-layer library dependency diagram
03 · Figma → code pipeline

The Figma component is the spec.

FigmaVue.js
Component nameVue SFC name. Button.fig → Button.vue
Component propertyVue prop with matching name and type. Variant=primary → variant: 'primary'
Boolean propertyVue boolean prop. Disabled=true → disabled: true
Slot propertyVue named slot. Leading → <slot name="leading" />
Variable (token)CSS custom property exported by Style Dictionary. color.bg.brand → --color-bg-brand
Variant matrixStorybook story per variant combination, generated from the same matrix.

Handoff protocol. Engineering reviews each component in Figma before build, using a fixed annotation block: purpose, props, states, accessibility, motion, do & don't. After build we diff it in dev mode against a checklist of states, and any mismatch is fixed at the component.

04 · Tooling & adoption

Two Figma plugins I built (vibe-coded), both in daily use.

Built with Cursor and Claude Code.

Plugin 01

Similar Component Finder

Problem: Designers in different modules kept recreating near-duplicates, and finding them took days.

What it does: Clusters near-duplicate components by structure and meaning, with side-by-side diffs to consolidate them.

Days → minutesAudit time
Pre-releaseUsed before every release
Plugin 02

Design Debt Collector

Problem: Detached instances, hardcoded colours, deprecated components and missing variants, none of it visible.

What it does: Audits files for all four and exports a triage report with file and frame references.

Ranked backlogWith file and frame refs
Weekly deltaShared in design review

What we measure. Two numbers, read out in design review every week: adoption (screens built on system components versus detached or hand-rolled ones) and design debt from the Debt Collector. Flat or rising debt means the contribution model is leaking somewhere.

One loop, start to finish. When the report flags a cluster of detached instances, we trace it back, usually to a frame older than the canonical component or a contributor who didn't know it existed. We rebuild that module on the system component, and the next week's report shows the delta.

05 · Governance & contribution

Governance model. ds-checklist-one.vercel.app ↗

RoleResponsibility
System owner (me)Roadmap, architecture, breaking changes, final review.
Core contributorsTwo designers and one front-end engineer. Triage intake, build and review components, maintain documentation.
Product contributorsAny designer or engineer outside the core. Can propose and build, with required review steps.

Quality gates. No component ships without passing all four:

  • A
    Accessibility
    WCAG 2.2 AA contrast, keyboard, focus and screen reader semantics.
  • C
    Consistency
    Tokens only, no hardcoded values, standard naming and variants.
  • D
    Documentation
    Purpose, props, states, motion, accessibility and do & don't filled in.
  • I
    Implementation parity
    Vue build reviewed against the Figma component before close-out.
06 · What I'd do differently
EARLIER

Lock the token JSON export contract with engineering on day one. We retrofitted it later and paid a small migration cost.

EARLIER

Start the Design Debt Collector plugin earlier. By the time it shipped, we already had a backlog of debt to triage.

EARLIER

Invest in dev-mode-ready annotations from the first component. Going back to annotate is slower than annotating as you build.

07 · Outcomes
250+
COMPONENTS · WEB +
MOBILE · MAPPED TO VUE.JS
Multi-mode
THEME · DARK · DENSITY ·
WHITE-LABEL
2
INTERNAL PLUGINS
IN DAILY USE
From zero
OCT 2024 →
NOW & ONGOING

Running the system as a living product, not a deliverable, is what keeps it healthy as the surface area grows.