Purpose: This document provides full context for AI assistants to continue work on this project.
Origin is a complete rewrite of the Origin Design System, shifting from a complex spec-generation pipeline to a simpler, designer-first workflow.
- Base UI for Behavior — Use Base UI unstyled components for accessibility and interaction logic
- Figma for Visuals — Extract CSS directly from Figma Dev Mode (already tokenized)
- Minimal Transformation — Reduce pipeline complexity to minimize drift between design and code
- Designer-First — The workflow is optimized for a designer who codes, not an engineer who designs
- Complex MCP spec-generation pipeline with many transformation steps
- Design drift accumulated at each transformation layer
- Heavy engineering overhead for maintaining generators
- Memory/context issues across sessions
Figma Design → Figma Lint Plugin → Base UI Component + Figma CSS → Done
A Figma plugin that validates component structures against Base UI's expected anatomy.
Features:
- ✅ 37 component rules (100% Base UI coverage)
- ✅ Detects missing required parts
- ✅ Suggests renames for aliased names (e.g., "Content" → "Panel")
- ✅ Auto-fix applies renames across all variants
- ✅ Only matches structural nodes (frames/groups), not text nodes
Usage:
- Select a component in Figma
- Run the plugin
- Review issues and click "Fix All" to auto-rename
Building the plugin:
cd tools/base-ui-lint
npm install
npm run buildThen import tools/base-ui-lint/manifest.json in Figma → Plugins → Development.
Rule files: tools/base-ui-lint/rules/*.json
Tokens are exported natively from Figma Variables in W3C DTCG format.
Token sources:
tokens/figma/origin/— Origin design system tokens (Dark, Light, Value)tokens/figma/baseline/— Baseline/primitive tokens
Build tokens:
npm run tokens:buildOutputs to src/tokens/_variables.scss.
213 vendored icons from Central Icons. Icons are extracted from @central-icons-react packages and committed to the repo, so consumers do not need a CENTRAL_LICENSE_KEY.
Key files:
CentralIcon.tsx— Main componenticon-registry.ts— Generated registry (do not edit directly)icons/— Vendored icon.mjsand.d.tsfilesscripts/extract-icons.mjs— Single source of truth for which icons to vendor
Usage:
import { CentralIcon } from '@/components/Icon';
<CentralIcon name="IconHome" size={24} />
<CentralIcon name="IconChevronDown" size={16} color="var(--text-secondary)" />Adding/updating icons:
npm run icons:extract # Regenerate vendored files + registryEdit the SECTIONS array in scripts/extract-icons.mjs to add new icons. The script copies files from node_modules, strips sourcemaps, generates icon-registry.ts, and validates.
Packages (devDependencies — only needed for extraction):
@central-icons-react/round-outlined-radius-3-stroke-1.5@central-icons-react/round-filled-radius-3-stroke-1.5@central-icons-react/round-outlined-radius-0-stroke-1.5
Opt-in interaction tracking for all interactive primitives. Products provide a single AnalyticsHandler via AnalyticsProvider; components emit structured InteractionInfo when an analyticsName prop is set.
Shared hooks:
useTrackedCallback— wraps click, change, submit, select callbacksuseTrackedOpenChange— wraps overlay open/close with duration tracking
Instrumented components: Button, Form, Dialog, AlertDialog, Menu, Popover, Command, ContextMenu, Select, Switch, Checkbox.Group, Radio.Group, Tabs, Toggle, ToggleGroup, Combobox, Accordion, Table, NavigationMenu, Sidebar, Pagination, Menu.Item, Command.Item
If no provider or analyticsName is present, the hooks are no-ops — zero cost for products that don't use analytics.
origin/
├── src/
│ ├── app/ # Next.js app
│ │ ├── globals.scss # Global styles + icon stroke CSS
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ │ └── Icon/ # CentralIcon system
│ │ ├── icons/ # Vendored icon files (generated)
│ │ └── icon-registry.ts # Icon registry (generated)
│ ├── lib/
│ │ └── dev-warn.ts # Dev-only warning utility
│ └── tokens/
│ ├── _variables.scss # Generated from Figma tokens
│ └── _mixins.scss # SCSS mixins
├── tokens/
│ └── figma/
│ ├── origin/ # Origin tokens (Dark, Light, Value)
│ └── baseline/ # Baseline tokens
├── tools/
│ └── base-ui-lint/ # Figma lint plugin
│ ├── rules/ # 37 component rule files
│ ├── src/ # Plugin source
│ └── dist/ # Built plugin
├── scripts/
│ ├── build-tokens.js # Token transformation script
│ └── extract-icons.mjs # Icon vendoring + registry generation
└── CONTEXT.md # This file
Base UI provides:
- Accessibility built-in
- Keyboard navigation
- ARIA attributes
- Focus management
- Compound component patterns
We style Base UI components with Figma-extracted CSS.
Icons are vendored from @central-icons-react into the repo:
- Consumers do not need a
CENTRAL_LICENSE_KEYto install Origin scripts/extract-icons.mjsis the single source of truth for which icons to includeicon-registry.tsandicons/are generated — do not edit directly- Tree-shaking still removes unused icons from bundle
The lint plugin ensures Figma components match Base UI's anatomy:
Accordion.Itemin Figma →Accordion.Itemin codePanelframe in Figma →Accordion.Panelin code
This makes the Figma-to-code translation trivial.
Base UI has distinct Dialog and AlertDialog components with different requirements:
- Dialog: Description optional
- AlertDialog: Description required (for accessibility)
The lint plugin only matches frames/groups/components, not text nodes. This prevents false positives from Figma's auto-naming of text layers.
- Design in Figma with proper frame structure
- Run Base UI Lint Plugin to validate/fix structure
- Copy CSS from Figma Dev Mode (already tokenized)
- Create React component using Base UI + copied CSS
- Done — no generation step, no spec files
Figma structure after linting:
Accordion / Item
├── Header
│ └── Trigger
│ ├── Title (text)
│ └── Icon
└── Panel
└── Content (text)
React component:
import { Accordion } from '@base-ui-components/react/accordion';
import styles from './Accordion.module.scss';
<Accordion.Root>
<Accordion.Item className={styles.Item}>
<Accordion.Header>
<Accordion.Trigger className={styles.Trigger}>
<span className={styles.Title}>{title}</span>
<CentralIcon name="IconChevronDown" />
</Accordion.Trigger>
</Accordion.Header>
<Accordion.Panel className={styles.Panel}>
{content}
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>- Build first component end-to-end — Use the lint plugin + Base UI + Figma CSS workflow
- Test the full flow — Validate that the approach works in practice
- Add Storybook stories — For component documentation
- CI/CD setup — Token validation, type checking
- CI/CD setup —
CENTRAL_LICENSE_KEYin secrets for icon extraction if needed
# Development
npm run dev # Start Next.js dev server
npm run storybook # Start Storybook
# Build
npm run build # Build Next.js
npm run tokens:build # Transform Figma tokens to SCSS
npm run icons:extract # Vendor icons + regenerate registry
# Lint plugin
cd tools/base-ui-lint
npm run build # Build the Figma pluginThe @central-icons-react packages are devDependencies used only for icon extraction (npm run icons:extract). Developers running extraction need CENTRAL_LICENSE_KEY set for npm install. Consumers of @lightsparkdev/origin do not need the key — icons are vendored into the repo.
Base UI was recently renamed:
- Old:
@base-ui-components/react - New:
@base-ui/react
We're currently using the old package name. Consider updating when stable.
The tools/ directory is excluded from the main tsconfig since it has Figma-specific types.
- Figma Design System: Set
FIGMA_FILE_KEYin.env.local— see.env.example - Base UI Docs: https://base-ui.com/react/components
This project was set up in a conversation that:
- Analyzed origin v1's complexity and identified pain points
- Proposed Base UI + Figma CSS as a simpler approach
- Built the Base UI lint plugin with 100% component coverage
- Set up the token system (origin + baseline)
- Ported the complete icon system
- Fixed several plugin bugs (variant handling, text node matching)
The project is ready for building the first real component using the new workflow.