| name | claude2figma-design-system-harness |
| description | Enforce Design System compliance in AI-generated Figma designs with 4 skills that bind components, tokens, and styles |
| triggers | ["set up figma design system skills","install claude2figma harness","enforce design tokens in figma","keep ai designs on design system rails","bind figma components to design tokens","start figma design system session","configure claude code figma skills","verify figma design system compliance"] |
claude2figma Design System Harness
Skill by ara.so — Design Skills collection.
A harness for Claude Code + Figma that enforces Design System compliance in AI-generated designs. Prevents hardcoded values, ensures components stay linked, and binds all visual properties to tokens and styles.
What This Does
When AI writes to Figma without guidance, it creates everything from scratch:
- Hardcoded hex colors instead of color tokens
- Raw spacing values instead of spacing variables
- Components rebuilt from primitives instead of instances
claude2figma fixes this with 4 Claude Code Skills:
- figma-preflight — 3-step parallel check that loads Token Map + Component Registry
- component-rules — Library-first lookup, Auto Layout patterns, semantic naming
- figma-style-binding — Enforces Variable/Style binding + post-write QA verification
- reference-interpreter — Converts screenshots/references → structured Design Brief
Every design operation follows: search DS → create Instances → bind tokens → verify.
Installation
Prerequisites
npm install -g @anthropic-ai/figma-mcp
Setup
git clone https://github.com/senlindesign/claude2figma.git
cd claude2figma
cp -r .claude/skills/* /path/to/your-project/.claude/skills/
cp .claude/settings.json /path/to/your-project/.claude/settings.json
cp CLAUDE.md.template /path/to/your-project/CLAUDE.md
Configure CLAUDE.md
# Figma Design Project
- **Figma file:** https://www.figma.com/design/YOUR_FILE_KEY/...
- **Fonts:** [leave blank — auto-detected by preflight]
- **Session goal:** Build login page with email/password fields
## Rules
1. Every visual value must bind to a Style or Variable.
2. Always search connected libraries before building any component from scratch.
3. Never start designing before the Design Brief is confirmed.
Key Skills Structure
Your project should have this structure after installation:
your-project/
├── CLAUDE.md # Config: Figma URL, fonts, rules
└── .claude/
├── settings.json # Permissions + QA Hook
└── skills/
├── figma-preflight/ # Skill 1: Parallel check + Token Map
│ └── SKILL.md
├── component-rules/ # Skill 2: Library-first patterns
│ └── SKILL.md
├── figma-style-binding/ # Skill 3: Token binding + QA
│ └── SKILL.md
└── reference-interpreter/ # Skill 4: Reference → Design Brief
└── SKILL.md
Usage Patterns
Pattern 1: Start Every Session with Preflight
const fileKey = extractFileKey(CLAUDE_MD_CONTENT);
const [mcpStatus, fileAccess, dsAssets] = await Promise.all([
checkMCPConnection(),
verifyFilePermissions(fileKey),
loadDesignSystemAssets(fileKey)
]);
const tokenMap = {
colors: await figma.getLocalVariableCollectionsAsync('COLOR'),
spacing: await figma.getLocalVariableCollectionsAsync('NUMBER'),
textStyles: await figma.getLocalTextStylesAsync(),
effectStyles: await figma.getLocalEffectStylesAsync()
};
const components = await figma.getLocalComponentsAsync();
const componentRegistry = components.map(c => ({
name: c.name,
id: c.id,
variantProperties: c.componentPropertyDefinitions
}));
Pattern 2: Component-First Design
const button = componentRegistry.find(c =>
c.name.toLowerCase().includes('button') &&
c.variantProperties?.variant?.includes('primary')
);
if (!button) {
throw new Error('No Button/Primary in DS — check library or request custom component');
}
const instance = figma.createInstance();
instance.mainComponent = figma.getNodeById(button.id);
instance.setProperties({ variant: 'primary', size: 'medium' });
if (instance.children[0].fills) {
const primaryColorVar = tokenMap.colors.find(v => v.name === 'primary');
instance.children[0].fills = [{
: ,
: { : , : , : },
: { : { : primaryColorVar. } }
}];
}
(instance);
Pattern 3: Token Binding Enforcement
node.fills = [{
type: 'SOLID',
boundVariables: { color: { id: tokenMap.colors.find(v => v.name === 'surface').id } }
}];
node.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
async function verifyTokenBindings(node) {
const violations = [];
if (node.fills && !node.fills[0]?.boundVariables) {
violations.push(`${node.name}: fills not bound to token`);
}
if (node.textStyleId === '') {
violations.push(`${node.name}: no text style bound`);
}
if (violations.length > 0) {
throw ();
}
}
Pattern 4: Reference-Driven Design
const designBrief = {
layout: 'Two-column grid, 16px gap',
components: [
{ type: 'Header', contains: ['Logo', 'Navigation/Horizontal', 'Button/Primary'] },
{ type: 'Hero Section', contains: ['Heading/H1', 'Body/Large', 'Button Group'] }
],
tokens: {
colors: ['primary', 'surface', 'on-surface'],
spacing: ['space-4', 'space-8', 'space-16'],
typography: ['heading-1', 'body-large']
}
};
Configuration
settings.json — QA Hook
{
"mcpServers": {
"figma": {
"command": "npx",
"args": ["-y", "@anthropic-ai/figma-mcp"]
}
},
"qaHooks": {
"postWrite": "verifyTokenBindings"
},
"permissions": {
"figma": ["read", "write"]
}
}
CLAUDE.md — Session Rules
# Figma Design Project
- **Figma file:** https://www.figma.com/design/ABC123/...
- **Session goal:** Build dashboard with data table and filters
## Rules
1. Run preflight before starting design work
2. Every component must be an Instance, not built from scratch
3. Every color, font, spacing must bind to a token
4. Take screenshot after each major section for verification
Real-World Workflow
$ claude-code chat
User: "let's start"
Claude:
✓ MCP connection verified
✓ File permissions confirmed
✓ Design System loaded: 47 tokens, 23 components
Ready to design. What are we building?
User: "Build a login form with email, password, and a submit button"
Claude:
[Searches Component Registry]
Found: Form/Vertical, Input/Email, Input/Password, Button/Primary
[Creates Instances + binds tokens]
- Form container: padding bound to space-6
- Input fields: text style bound to body-medium
- Submit button: fills bound to primary color token
[Takes screenshot]
✓ Verification passed — all tokens bound
Screenshot: [shows form in Figma]
User: "Add a forgot password link below the form"
Claude:
[Searches for Link component]
Not found in registry — creating text node with hyperlink style
[Binds text style + color token]
✓ Verification passed
Troubleshooting
Error: "No components found in registry"
Error: "Invalid variant property value"
const component = figma.getNodeById(componentId);
const validVariants = component.componentPropertyDefinitions.variant.variantOptions;
instance.setProperties({ variant: validVariants[0] });
Error: "Token binding verification failed"
node.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.4, b: 0.8 } }];
const token = tokenMap.colors.find(v => v.name === 'primary');
node.fills = [{
type: 'SOLID',
boundVariables: { color: { id: token.id } }
}];
Working with Library Variables (Can't See Them Locally)
const libraryVarKey = 'VariableID:123:456';
const importedVar = await figma.variables.importVariableByKeyAsync(libraryVarKey);
frame.fills = [{
type: 'SOLID',
boundVariables: { color: { id: importedVar.id } }
}];
Best Practices
- Always run preflight at session start — loads Token Map + Component Registry
- Search before creating — check componentRegistry before building any UI element
- Bind, don't hardcode — every visual property must reference a token
- Verify after write — QA hook catches token binding violations automatically
- Confirm Design Brief — when working from reference, output structured brief before building
API Reference
Key Figma MCP Methods
const file = await figma.getFileAsync(fileKey);
const variables = await figma.getLocalVariableCollectionsAsync();
const textStyles = await figma.getLocalTextStylesAsync();
const components = await figma.getLocalComponentsAsync();
const instance = figma.createInstance();
instance.mainComponent = masterComponent;
instance.setProperties({ variant: 'primary' });
node.fills = [{
type: 'SOLID',
boundVariables: { color: { id: variableId } }
}];
node.textStyleId = textStyle.id;
const bindings = node.boundVariables;
const hasColorBinding = bindings?.fills?.[0]?.color !== undefined;
When to Use This
| ✅ Good For | ❌ Not For |
|---|
| Building pages from existing DS | Creating a DS from scratch |
| Natural language → Figma design | Pixel-perfect illustration |
| Ensuring 100% token compliance | FigJam / whiteboard work |
| Working in DS file or with linked library | Free-form design without DS |
License: MIT
Repository: https://github.com/senlindesign/claude2figma
Figma MCP Server: https://www.npmjs.com/package/@anthropic-ai/figma-mcp