Skip to main content
SR

AI Engineering Lab

I define tokens, components and rules once. Your team uses them in React, Angular, Vue, Swift or Kotlin, and your agents read them instead of guessing: less repeated code, fewer tokens spent and fewer fixes in review.

This page is the proof: one source of truth, rendered for people and published for agents. AI speeds up the implementation; the architecture, accessibility and final review stay with me.

See the system

Everything on this page comes from the same tokens and specs. No AI API, no database.

For your team

  • One component, five stacks: React, Angular, Vue, Swift and Kotlin
  • Change a token once and every app follows
  • Specs with usage and accessibility rules built in

For your agents

  • Spec, tokens and code from a public JSON registry
  • Rules to follow instead of styles to guess
  • A check that catches hardcoded values before review
01One source of truth

One system, every stack.

Tokens and specs are written once. Style Dictionary turns tokens/lab.tokens.json into CSS variables, SwiftUI and Jetpack Compose, and every stack below gets the same Card from the same templates. Change the primary colour and all five follow.

Change primary color

#E23A0D

Same token as the playground's Accent.

From the playground

Variantelevated

Radius8px

Pick Card in the playground to change the variant.

One change, every output

  • tokens.cssReact · Angular · Vue

    --ds-color-primary: #e23a0d;
  • Tokens.swiftSwift

    public static let colorPrimary = Color(red: 0.886, green: 0.227, blue: 0.051, opacity: 1)
  • Tokens.ktKotlin

    val colorPrimary = Color(0xffe23a0d)

Primary is #E23A0D in React, Angular, Vue, Swift and Kotlin.

Live preview · webcard · elevated · 8px · #E23A0D

Tokens, not hex codes

The image is a placeholder.

The live preview renders this example with the same card.css and button.css.
import type { CSSProperties } from "react"import { Button } from "./Button"import { Card, cardParts } from "./Card" // The card in the lab: an image, a title and a primary Button as its action. const media: CSSProperties = {  width: "100%",  aspectRatio: "16 / 9",  objectFit: "cover",  borderRadius: "calc(var(--ds-radius-card) / 2)",} export function CardExample() {  return (    <Card variant="elevated" size="md">      <img src="/cover.jpg" alt="" style={media} />      <h3 className={cardParts.title}>Tokens, not hex codes</h3>      <Button variant="primary">Read the docs</Button>    </Card>  )} 

Spec

specs/card.spec.json · What the component is, how to use it and which tokens it reads. The code above takes its variants, sizes and defaults from it.

{  "$schema": "./schema/component-spec.schema.json",  "name": "Card",  "description": "A surface that groups related content, such as a title, a short text and one action.",  "source": "components/lab/demo-components.tsx (styles: RECIPES.card in lib/lab/playground.ts)",  "element": "article",  "extends": "HTMLAttributes<HTMLElement>",  "whenToUse": [    "Group related content with at most one main action: a project, an article, a setting summary.",    "Show several items of the same kind side by side, each in its own Card."  ],  "whenNotToUse": [    "As a clickable surface: Card has no button role or keyboard handling. Put a link or a Button inside it instead.",    "For page layout or whole sections: use plain layout elements."  ],  "props": [    {      "name": "variant",      "type": "enum",      "values": [        "elevated",        "outlined",        "filled"      ],      "default": "elevated",      "required": false,      "description": "Surface style: shadow, hairline border or a tint of color.primary."    },    {      "name": "size",      "type": "enum",      "values": [        "sm",        "md",        "lg"      ],      "default": "md",      "required": false,      "description": "Padding and maximum width, from RECIPES.card.sizes."    },    {      "name": "disabled",      "type": "boolean",      "default": false,      "required": false,      "description": "Sets aria-disabled, dims the card to 50% and blocks pointer events."    },    {      "name": "children",      "type": "node",      "default": null,      "required": false,      "description": "The content, styled with cardParts (eyebrow, title, body, action)."    },    {      "name": "className",      "type": "string",      "default": null,      "required": false,      "description": "Extra classes, merged after the recipe with cn()."    }  ],  "variants": [    "elevated",    "outlined",    "filled"  ],  "sizes": [    "sm",    "md",    "lg"  ],  "states": [    {      "name": "default",      "description": "elevated: color.surface with a soft shadow. outlined: transparent with a color.border hairline. filled: color.surface tinted 10% with color.primary."    },    {      "name": "hover",      "description": "elevated: deeper shadow. outlined: the border turns color.primary. filled: the tint grows to 16%. data-force=\"hover\" pins this state for docs and visual tests."    },    {      "name": "disabled",      "description": "aria-disabled=\"true\", 50% opacity and no pointer events."    }  ],  "tokens": [    {      "path": "color.surface",      "usage": "elevated background, and the base of the filled tint."    },    {      "path": "color.text",      "usage": "Text colour."    },    {      "path": "color.muted",      "usage": "cardParts.body text."    },    {      "path": "color.primary",      "usage": "Eyebrow and action text, outlined hover border, filled tint, action focus ring."    },    {      "path": "color.border",      "usage": "outlined border."    },    {      "path": "radius.card",      "usage": "Corner radius; the action's focus ring uses half of it."    },    {      "path": "space.sm",      "usage": "Padding at size sm (the web recipe's p-4 has the same value)."    },    {      "path": "space.md",      "usage": "Padding at size md (p-5, same value)."    },    {      "path": "space.lg",      "usage": "Padding at size lg (p-6, same value)."    },    {      "path": "fontSize.title",      "usage": "cardParts.title text (text-base, same value)."    },    {      "path": "fontSize.body",      "usage": "cardParts.body and cardParts.action text (text-sm, same value)."    }  ],  "accessibility": {    "role": "article, from the native <article> element. The Card itself is not interactive.",    "keyboard": [      "The Card is not focusable; Tab reaches the links or buttons inside it.",      "When disabled, also take inner actions out of the tab order (tabIndex={-1}): aria-disabled and pointer-events do not do that."    ],    "focus": "The action (cardParts.action) shows a 2px color.primary ring on focus-visible. Inner Buttons keep their own ring.",    "contrast": "Title and body text at least 4.5:1 against the card background in every variant (WCAG 2.2 AA, 1.4.3).",    "labels": "Start the content with a heading (cardParts.title) so the article can be found by heading navigation."  },  "composition": [    "Content goes inside as children, styled with cardParts: eyebrow, title, body and action.",    "cardParts.action styles a link. A Button can be the action instead, as in the 'One system, every stack' Card, which composes an image, a title and a primary Button."  ],  "example": {    "language": "tsx",    "code": "<Card variant=\"elevated\" size=\"md\">\n  <p className={cardParts.eyebrow}>Design system</p>\n  <h3 className={cardParts.title}>Tokens, not hex codes</h3>\n  <p className={cardParts.body}>Components read semantic tokens.</p>\n  <a href=\"/system\" className={cardParts.action}>Read the docs</a>\n</Card>"  }}
tokens/lab.tokens.jsonSource of truth

The source file, with your primary and radius edits applied. Every stack above is built from it.

{  "color": {    "surface": {      "$type": "color",      "$value": "#1B1C21",      "$description": "Card background"    },    "text": {      "$type": "color",      "$value": "#F2F2F4",      "$description": "Primary text on surface"    },    "muted": {      "$type": "color",      "$value": "#A0A0AB",      "$description": "Secondary text: card body, hints, placeholders"    },    "primary": {      "$type": "color",      "$value": "#E23A0D",      "$description": "Brand accent: buttons, links, focus"    },    "onPrimary": {      "$type": "color",      "$value": "#111111",      "$description": "Text on primary, picked for contrast"    },    "border": {      "$type": "color",      "$value": "#2E3037",      "$description": "Hairlines and outlined variants"    }  },  "radius": {    "card": {      "$type": "dimension",      "$value": "0.5rem"    },    "button": {      "$type": "dimension",      "$value": "0.5rem"    },    "input": {      "$type": "dimension",      "$value": "0.5rem"    }  },  "space": {    "sm": {      "$type": "dimension",      "$value": "1rem"    },    "md": {      "$type": "dimension",      "$value": "1.25rem"    },    "lg": {      "$type": "dimension",      "$value": "1.5rem"    }  },  "fontSize": {    "title": {      "$type": "fontSize",      "$value": "1rem"    },    "body": {      "$type": "fontSize",      "$value": "0.875rem"    }  }}
02For people

Change the design, read the code.

A designer or developer tunes the component and gets code that matches. Every control updates the live component and the code at the same time; the preview renders the exact React component shown in the panel.

Controls

Component

Variant

Size

Theme

State

8px

Accent

#E23A0D
Live previewbutton · primary · md · default
Text on accent: 4.36:1 AA large--ui-radius: 8px--ui-accent:#E23A0D
Framework
This is the code the preview is running.
import { forwardRef, type ButtonHTMLAttributes } from "react"import { cn } from "@/lib/utils" const base = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--ui-radius)] font-medium transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--ui-canvas)] disabled:cursor-not-allowed disabled:opacity-50" const sizes = {  sm: "h-8 px-3 text-[13px]",  md: "h-10 px-4 text-sm",  lg: "h-12 px-5 text-base",} as const const variants = {  primary: "bg-[var(--ui-accent)] text-[var(--ui-on-accent)] enabled:hover:bg-[var(--ui-accent-hover)] data-[force=hover]:bg-[var(--ui-accent-hover)]",  secondary: "border border-[var(--ui-border)] bg-[var(--ui-surface)] text-[var(--ui-fg)] enabled:hover:border-[var(--ui-accent)] data-[force=hover]:border-[var(--ui-accent)]",  ghost: "bg-transparent text-[var(--ui-accent)] enabled:hover:bg-[color-mix(in_srgb,var(--ui-accent)_12%,transparent)] data-[force=hover]:bg-[color-mix(in_srgb,var(--ui-accent)_12%,transparent)]",} as const export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {  variant?: keyof typeof variants  size?: keyof typeof sizes} export const Button = forwardRef<HTMLButtonElement, ButtonProps>(  ({ variant = "primary", size = "md", type = "button", className, ...props }, ref) => (    <button      ref={ref}      type={type}      className={cn(base, sizes[size], variants[variant], className)}      {...props}    />  ),)Button.displayName = "Button"
03For agents

Built for agents, not just people.

The same system is published as a public registry, so an agent reads the right spec, tokens and code instead of guessing from screenshots or writing the component again.

What it saves, measured on this page

What an agent reads to build the Card and Button for Angular: the registry's answer, not the source files.
22 KBinstead of 49 KB
The Angular Card component. Its CSS (104 lines) is written once and shared by React, Angular and Vue.
32 lines
Caught by validate_usage in the answer written without the system, before anyone reviews it.
7 issues
Source files compared

AGENTS.md, tokens/lab.tokens.json, specs/card.spec.json, specs/button.spec.json, lib/lab/stacks.ts, lib/lab/component-css.ts, lib/lab/templates/shared.ts, lib/lab/templates/card.ts, lib/lab/templates/button.ts

Measured on this demo when the page is built. Not a benchmark of a real project.

Public registry

Live

Static, read-only JSON, generated at build time from the same tokens, specs and templates. CORS is open, so any tool can fetch it.

  • GET/r/index.json

    Every component, its variants and sizes, and the supported stacks.

    Open/r/index.json
  • GET/r/tokens.json

    The full token set, with values and their CSS, Swift and Kotlin names.

    Open/r/tokens.json
  • GET/r/rules.json

    The agent rules: AGENTS.md plus each spec's accessibility rules.

    Open/r/rules.json
  • GET/r/card.json?stack=angular

    One component: spec, tokens and code. Stacks: react, angular, vue, swift, kotlin.

The MCP below is a conceptual demo of what I would set up for your team: no MCP server runs on this site. The public registry above is the part that works today.

MCP demo

Illustrative
Example configExample

How a developer would connect an MCP server in Claude Code (.mcp.json) or Cursor (.cursor/mcp.json). The address is a placeholder: there is no server behind it.

{  "mcpServers": {    "design-system": {      "type": "http",      "url": "https://design-system.example/mcp"    }  }}
Guided conversationStep 1/7

The requests are a script; the responses are real, computed in your browser from the same core that serves /r.

Developer

Using the design system MCP, build a settings card with an image and a save button for my Angular app.

Before and after

The same request, answered without and with the design system.

Without the design system

Illustrative · written by hand

A typical generic answer: hardcoded colours and sizes, a div as a button (no role, no keyboard), and a placeholder instead of a label.

<!-- settings-card.component.html --><div class="card" style="background: #1e1e1e; border-radius: 12px; padding: 20px">  <img src="cover.jpg" />  <h3 style="color: #ffffff; font-size: 18px">Notification settings</h3>  <input placeholder="Email" style="border: 1px solid #333333" />  <div class="btn bg-blue-600" style="color: #ffffff; padding: 10px 16px" (click)="save()">    Save  </div></div>

validate_usage on its props

Buttoninvalid

  • errorclassName · Palette colour class bg-blue-600 bypasses the tokens.
  • errorstyle.color · Hardcoded colour #ffffff.
  • errorstyle.padding · Hardcoded size 10px.
  • errorstyle.padding · Hardcoded size 16px.

Inputinvalid

  • errorstyle.border · Hardcoded colour #333333.
  • errorstyle.border · Hardcoded size 1px.
  • errorlabel · label is required and rendered as a visible <label for>. Do not use the placeholder as the label. The hint is announced through aria-describedby.

With the design system

Generated from the registry

Card and Button from the registry, styled only with tokens, with a real <button> and the spec's focus styles.

import { Component } from "@angular/core"import { ButtonComponent } from "./button.component"import { CardComponent } from "./card.component" // The card in the lab: an image, a title and a primary Button as its action.@Component({  selector: "app-card-example",  standalone: true,  imports: [CardComponent, ButtonComponent],  template: `    <ds-card variant="elevated" size="md">      <img class="media" src="/cover.jpg" alt="" />      <h3 class="ds-card__title">Notification settings</h3>      <button dsButton variant="primary">Save changes</button>    </ds-card>  `,  styles: `    .media {      width: 100%;      aspect-ratio: 16 / 9;      object-fit: cover;      border-radius: calc(var(--ds-radius-card) / 2);    }  `,})export class CardExampleComponent {} 

validate_usage on its props

Buttonvalid

04How I work

From design to production, with someone accountable.

The workflow behind the system: what AI speeds up, what I decide, and how a vague first pass becomes a reviewed component.

Four steps, one person accountable.

How a component moves from a design to production. Pick a step to see what AI speeds up and what I decide.

Objective

Turn the Figma component into an explicit spec that both people and agents can implement without guessing.

Example input

specs/button.md

component: Buttonvariants: primary | secondary | ghostsizes: sm 32 · md 40 · lg 48tokens: --ui-accent --ui-on-accent --ui-radiusstates: default · hover · focus-visible · disabled · loadinga11y: native <button>, visible focus ring, aria-busy while loadingapi: extends ButtonHTMLAttributes, forwardRef, no boolean flags

What AI helps with

  • Reading variables and variants from Figma through Figma MCP
  • Drafting the spec and listing edge cases I might miss
  • Recalling past decisions and conventions stored in Engram

What I review or decide

  • The component API and naming
  • Which states exist, and what is out of scope
  • How design values map to existing tokens

Risks and how I handle them

  • The spec copies pixel values from FigmaMap every value to a token before implementation
  • States are forgotten (loading, disabled, focus)A fixed state checklist in every spec

Output

A reviewed spec with acceptance criteria.

Same button, two levels of intent.

A first pass from an underspecified prompt, next to the version after review. The first pass is not bad because AI wrote it, but because the request was vague. With the spec from step 1, the first draft lands much closer to the refined one.

Highlighted lines in the refined version: Accessibility

import { forwardRef, type ButtonHTMLAttributes } from "react"import { cn } from "@/lib/utils"import { Spinner } from "./spinner"import { buttonRecipe, type ButtonSize, type ButtonVariant } from "./button.recipe" export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {  variant?: ButtonVariant  size?: ButtonSize  loading?: boolean} export const Button = forwardRef<HTMLButtonElement, ButtonProps>(  (    { variant = "primary", size = "md", loading = false, disabled, type = "button", className, children, ...props },    ref,  ) => (    <button      ref={ref}      type={type}      disabled={disabled || loading}      aria-busy={loading || undefined}      className={cn(buttonRecipe({ variant, size }), className)}      {...props}    >      {loading && <Spinner aria-hidden="true" />}      <span className={cn(loading && "opacity-70")}>{children}</span>    </button>  ),)Button.displayName = "Button"

Inspect a difference

Accessibility

Why

A native <button> brings keyboard support, focus and the right role for free. type="button" avoids accidental form submits, aria-busy announces loading, and the label stays in place so screen readers still read it.

Trade-off

None worth avoiding here, since a styled <div> needs role, tabIndex and key handlers to get only part of this.

Where each tool fits.

Tools I use in this workflow. They are not connected to this page, they are a map of how I work.

Tools

  • Figma
  • Figma variables

Activities

  • User flows and component design
  • Variables for colour, spacing and radius

Deliverables

  • Figma frames
  • Token set
05Engineering principles

What I optimise for.

  • P01

    Reusable, maintainable components

    One recipe drives every variant and size; the playground prints the same source it renders.

    See the playground
  • P02

    Accessible interfaces

    Native elements, visible focus, labelled inputs and announced states, the first thing I check in review.

    See the accessibility diff
  • P03

    Consistent design systems

    Components read semantic tokens, so theme, radius and accent change through configuration, not edits.

    Change the tokens
  • P04

    Type safety and predictable state

    Unions over boolean flags; a single config object is the only state the playground has.

    See the API diff
  • P05

    Performance and responsive behaviour

    This page ships no highlighting library and calls no API; the code view is a small local tokenizer.

    See the process
  • P06

    Human review of AI-generated code

    AI drafts, I review: keyboard, screen reader, API ergonomics and visual QA before anything ships.

    See step 3
  • P07

    Fast iteration, no unnecessary complexity

    Small diffs, no new dependencies unless they pay for themselves, abstractions only when there is a second use.

    See the workflow

Want this for your team?

If your team rewrites the same components in every app, or your agents keep inventing styles, I can set up the tokens, specs, components and registry for your product.