Skip to content

v1.40.0 — Design System Extraction

Latest

Choose a tag to compare

@tpitre tpitre released this 16 Aug 22:50

Design System Extraction — turn a production codebase into a design system. Server-only: no plugin re-import needed (nothing in figma-desktop-bridge/ changed).

Seven new figma_ds_* tools plus a supporting extraction engine (src/core/extraction/). The workflow runs in order: analyze the app(s) → extract tokens → scaffold the package → wire Storybook → port components one at a time → verify with deterministic evals — and, for design-led orgs, import the extracted tokens into Figma variables with figma_import_tokens (top-level groups become collections), a full code → design system → Figma round-trip. Local Mode only: these tools read a production codebase and write a design-system package on the local filesystem, which Cloudflare Workers cannot do — so they are registered only in src/local.ts and never appear in Cloud Mode's tool list (the registerMultiFileTools precedent: no silent no-op is possible).

Added

  • figma_ds_analyze — scan one or more production app codebases. Detects framework (React/Next/Angular/Web Components), styling methods (Tailwind v3/v4, CSS Modules, SCSS, Emotion, styled-components), and vendor component layers (shadcn/ui, Radix, MUI, Chakra, etc.), then builds a component inventory with per-component classification (vendored / wrapped / pure-vendor / bespoke), prop contracts, real usage counts (porting rank), observed prop values from call sites (variant inference), and duplicate detection. Iconography and typography rules are captured for the scaffold's showcase pages. Multiple targets merge into one inventory with cross-app duplicates flagged — the shared design language of a product family.
    • Architecture classification — the "UI kit vs design system" analysis. An app ships FollowButton, ModerationMenu, NodeCard — components named after usage. A design system ships Button, Menu, Card, with usage expressed as variants and recipes. The analyzer assigns each component an atomic level, detects specializations (FollowButtonButton), and derives missingPrimitives: the canonical generic components the specializations imply but that don't exist in the codebase — which is the design-system build list, reviewed with the user rather than decided silently.
    • Writes the full manifest to <outDir>/.extraction/analysis.json and returns a compressed summary, so a large inventory doesn't blow the context window.
  • figma_ds_extract_tokens — mine the app's de-facto styling into DTCG tokens. Two confidence tiers. Declared styling intent is mined first and always becomes tokens: :root/@theme custom properties with multi-mode detection across theming conventions (.dark, [data-theme=…], [data-mode=…], theme classes, prefers-color-scheme — light + dark blocks become token modes), SCSS variables, tailwind.config theme values, and shadcn HSL triples. Inferred values come second: recurring raw values (hex colors, spacing/radius/font sizes) are promoted only above a frequency threshold (minFrequency, default 4), and everything below the threshold is listed in the report for human review instead of silently dropped. Tailwind utility classes used in markup are frequency-mined and valued from the app's own installed theme (node_modules/tailwindcss/theme.css), so mined values are version-accurate rather than guessed from a hardcoded palette.
    • Every token carries provenance — source file:line, confidence tier, frequency — in $extensions, so a reviewer can trace any token back to the code that justified it.
    • Output goes through the same formatter engine as figma_export_tokens (canonical DTCG always; CSS vars / Tailwind v4 / Tailwind v3 / SCSS / TS / JSON / Style Dictionary / Tokens Studio on request; both DTCG dialects). The DTCG file is directly importable into Figma variables via figma_import_tokens.
    • Names stay structural as mined (--color-blue-500color/blue/500). Semantic naming (color/primary) is deliberately a review pass with the user, layered on top as aliases — a judgment call, not something to guess.
  • figma_ds_scaffold — generate the design-system package. package.json with the app framework as peer deps, src/components layout, token files via the shared formatter engine, framework-neutral token/typography/iconography showcase MDX docs pages, and a README documenting the workflow. Additive by default — existing files are skipped unless force (token files always refresh). Storybook itself is deliberately not baked in: run npm create storybook@latest inside the package afterwards — the CLI detects the framework and installs the current version, so the scaffold never ships version-pinned Storybook templates that rot.
  • figma_ds_setup_storybook — wire the fresh workshop to the extraction. A stock npm create storybook@latest workshop knows nothing about the source app, and every piece of glue this tool generates corresponds to a real render-fidelity failure hit during live extraction runs: .storybook/preview.css (Tailwind entry importing the extracted tokens plus the source app's @theme utility mapping, custom @utility definitions, @layer base, and @font-face rules mined from its stylesheets, with a dark variant covering both .dark and [data-theme] conventions), self-hosted font files copied into staticDirs with runtime-var fallbacks, a main.js patch (Tailwind vite plugin + automatic JSX runtime — without it, stories die with React is not defined), and a preview.jsx patch (preview.css import + a theme toolbar/decorator that sets both mode conventions, using the extracted mode names). Idempotent; anything it can't patch safely is returned as a manual step.
  • figma_ds_extract_component — per-component deep manifest for porting. Source (capped at 64KB), local import closure, prop contract, observed call-site variants, vendor classification, style touchpoints (classNames, CSS-module imports, custom properties consumed — check these against tokens.json), and a ready-to-adapt CSF3 story scaffold with one story per real observed variant. Pure-vendor components return guidance instead of source: represent them via the token theme and document approved usage, or wrap them in the design system if the org needs a customized version.
  • figma_ds_verify — deterministic fidelity evals. The governance gate before handing the package over or pushing tokens to Figma. Checks: tokens.json parses as DTCG and every alias resolves (import-ready); no quoted CSS functional expressions in generated token files (see Fixed — this class of bug shipped and was caught live); every var() consumed in component/preview CSS resolves somewhere in the workshop; every component directory carries a stories file and index barrel; every portable inventory component has a recorded porting status. Each check encodes a failure class found in real extraction runs. Also reports Figma round-trip readiness with the exact figma_import_tokens call for design-led orgs.
  • figma_ds_status — porting progress across sessions. Read a progress summary, or record a component as pending / in-progress / ported / skipped with notes and its story file. Persisted in <outDir>/.extraction/status.json, so an engagement spanning dozens of components and many sessions resumes where it left off instead of re-deriving what's done.

Fixed

  • Token formatters quoted CSS functional expressions, silently killing transitions. The CSS-variables, SCSS, and Tailwind v4 formatters share a needsQuoting() heuristic for string-typed token values, and it treated functional expressions as string literals — so an easing token rendered as --easing-standard: "cubic-bezier(0.4, 0, 0.2, 1)";. That is syntactically valid CSS, which is what makes it dangerous: nothing errors, the variable simply makes every declaration that consumes it invalid, and the effect is a transition that doesn't animate. Found live during extraction validation — a quoted cubic-bezier easing killed a button's hover transition with no diagnostic anywhere. Functional expressions (cubic-bezier(...), calc(...), clamp(...), var(...), color-mix(...), etc.) are now recognized as CSS values and emitted unquoted. This affects figma_export_tokens output too, not just the new extraction tools — if your exported tokens include easing, duration, or calc values, re-export to pick up the fix. figma_ds_verify includes a quoted-expression scan so a regression of this class fails an eval instead of shipping.
  • figma_lint_design's AI-facing description undersold its design-system checks. The token-misuse rule — a semantic token bound to the wrong property, e.g. a bg/* or surface/* variable used as a text fill — was live in the audit, but the tool description still listed only four design-system rules. Clients that choose rules from the description had no way to know the check existed. The description now lists all five.

Internal

  • New extraction engine under src/core/extraction/ (walker, detectors, component inventory, architecture classifier, token extractor, scaffolder, Storybook preset, verifier) — dependency-free scanning: package.json evidence plus file evidence, no AST, no execution of user code. New Jest suite tests/design-system-extraction.test.ts exercises it against fixture codebases in tests/fixtures/.