Claude Code can build entire features autonomously—multi-file changes, complex logic, full CRUD flows. But there's a catch: without design system integration, every feature it builds looks different.
You get functional code with inconsistent styling. Blue buttons in one feature, indigo in another. Spacing that's "close enough" but never quite right. Six months later, your codebase is a design system graveyard.
This guide shows how to integrate design tokens with Claude Code so it builds features that match your brand from the start.
The Autonomous Coding Problem
Claude Code's power is its ability to work independently. You say "build a user management dashboard" and it:
- Creates the page layout
- Builds CRUD components
- Adds form validation
- Implements API calls
- Writes tests
All without asking for styling decisions at each step.
That's the problem. It has to make styling decisions, so it falls back to common patterns:
// Claude's default generation without tokens
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="bg-white shadow rounded-lg p-6">
<h1 className="text-2xl font-bold text-gray-900 mb-4">
User Management
</h1>
<button className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
Add User
</button>
</div>
</div>
This code:
- ✅ Works correctly
- ✅ Follows React best practices
- ✅ Is properly structured
- ❌ Uses arbitrary Tailwind defaults
- ❌ Doesn't match your brand colors
- ❌ Ignores your spacing system
- ❌ Won't survive design review
The solution isn't to micromanage every component. It's to give Claude Code the constraints it needs to make good decisions autonomously.
Integration Architecture
Design system integration with Claude Code requires three layers:
┌─────────────────────────────────┐
│ Claude Code Instructions │ ← How to use tokens
├─────────────────────────────────┤
│ Token Package + Config │ ← What tokens exist
├─────────────────────────────────┤
│ Project Setup (Tailwind/CSS) │ ← How tokens apply
└─────────────────────────────────┘
Each layer reinforces the others. Let's build them.
Layer 1: Install Design Tokens
Add FramingUI to your project:
npm install @framingui/tokens @framingui/tailwind-preset
For projects using CSS variables instead of Tailwind:
npm install @framingui/tokens
npx framingui export --format css --output src/styles/design-tokens.css
Import in your root layout:
// app/layout.tsx or _app.tsx
import '@/styles/design-tokens.css';
Layer 2: Configure Tailwind Integration
Update tailwind.config.ts:
import type { Config } from 'tailwindcss';
import { framinguiPreset } from '@framingui/tailwind-preset';
const config: Config = {
presets: [framinguiPreset],
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
// Your custom extensions
},
},
};
export default config;
The preset maps FramingUI tokens to Tailwind classes:
bg-primary→ your primary brand colortext-content→ your default text colorp-4→ your spacing scale value 4 (1rem)rounded-base→ your default border radiustext-heading-lg→ your large heading style
Layer 3: Claude Code Custom Instructions
This is the critical piece. Claude Code needs explicit instructions on using your design system.
Create .claude/instructions.md in your project root:
# Design System Integration Rules
## Mandatory: Always Use Design Tokens
When generating UI components, **ALWAYS** use FramingUI design tokens. Never use arbitrary Tailwind values or custom colors.
## Token Categories
### Colors
Use semantic color tokens:
- **Backgrounds:** `bg-background`, `bg-card`, `bg-accent`
- **Text:** `text-content`, `text-muted-foreground`, `text-content-inverse`
- **Borders:** `border-border`, `border-input`
- **Brand:** `bg-primary`, `bg-secondary`, `text-primary-foreground`
- **Status:** `bg-success`, `bg-destructive`, `bg-warning`, `bg-info`
**Never use:** `bg-white`, `bg-gray-100`, `text-black`, `bg-blue-500`, hex colors
### Spacing
Use spacing scale tokens: `p-{n}`, `m-{n}`, `gap-{n}`, `space-{n}`
- Common values: `2` (0.5rem), `3` (0.75rem), `4` (1rem), `6` (1.5rem), `8` (2rem)
- **Never use:** arbitrary values like `p-[14px]`, `m-[18px]`
### Typography
Use semantic text tokens:
- **Headings:** `text-heading-xl`, `text-heading-lg`, `text-heading-md`, `text-heading-sm`
- **Body:** `text-body-lg`, `text-body`, `text-body-sm`
- **UI:** `text-caption`, `text-label`
**Never use:** `text-2xl`, `text-base`, `text-sm`, arbitrary font sizes
### Border Radius
Use radius tokens:
- `rounded-sm` (small elements, badges)
- `rounded-base` (default, buttons, inputs)
- `rounded-lg` (cards, modals)
- `rounded-full` (pills, avatars)
**Never use:** `rounded`, `rounded-md`, arbitrary values
### Shadows & Elevation
Use shadow tokens:
- `shadow-sm` (subtle elevation)
- `shadow-base` (default cards)
- `shadow-lg` (modals, popovers)
## Component Patterns
### Button Component
```tsx
<button
className={cn(
'inline-flex items-center justify-center',
'rounded-base font-medium transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
'disabled:pointer-events-none disabled:opacity-50',
{
'bg-primary text-primary-foreground hover:bg-primary/90': variant === 'primary',
'bg-secondary text-secondary-foreground hover:bg-secondary/80': variant === 'secondary',
'border border-input bg-background hover:bg-accent hover:text-accent-foreground': variant === 'outline',
},
{
'h-9 px-3 text-body-sm': size === 'sm',
'h-10 px-4 text-body': size === 'md',
'h-11 px-6 text-body-lg': size === 'lg',
}
)}
>
{children}
</button>
Card Component
<div className="rounded-lg border border-border bg-card p-6 shadow-base">
<h3 className="text-heading-md mb-4">{title}</h3>
<p className="text-body text-muted-foreground">{description}</p>
</div>
Form Input
<input
className={cn(
'flex h-10 w-full rounded-base border border-input',
'bg-background px-3 py-2 text-body',
'ring-offset-background',
'placeholder:text-muted-foreground',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
'disabled:cursor-not-allowed disabled:opacity-50'
)}
/>
File Organization
- UI Components:
src/components/ui/ - Feature Components:
src/components/[feature]/ - Utilities:
src/lib/utils.ts(forcnhelper) - Types:
src/types/
Accessibility Requirements
Every interactive component must include:
- Proper ARIA labels
- Keyboard navigation support
- Focus visible states (using
focus-visible:ring-2 focus-visible:ring-ring) - Disabled states with proper opacity and cursor
Token Import When Needed
For programmatic access to token values:
import { tokens } from '@framingui/tokens';
const primaryColor = tokens.color.primary.base;
const spacing4 = tokens.spacing[4];
Validation
Before marking a feature complete:
- ✅ All colors use semantic tokens
- ✅ All spacing uses scale tokens
- ✅ All text uses typography tokens
- ✅ All interactive elements are accessible
- ✅ No arbitrary Tailwind values in code
Examples of WRONG vs RIGHT
❌ Wrong
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-2xl font-bold text-gray-900 mb-4">Title</h2>
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Click me
</button>
</div>
✅ Right
<div className="bg-card rounded-lg shadow-base border border-border p-6">
<h2 className="text-heading-lg mb-4">Title</h2>
<button className="bg-primary text-primary-foreground px-4 py-2 rounded-base hover:bg-primary/90">
Click me
</button>
</div>
When in doubt, reference existing components in src/components/ui/ for patterns.
## Layer 4: Initialize Project Context
Claude Code reads project context from specific files. Create a `PROJECT_CONTEXT.md`:
```markdown
# Project Context for Claude Code
## Design System
This project uses **FramingUI** design tokens for all styling.
- Tokens package: `@framingui/tokens`
- Tailwind preset: `@framingui/tailwind-preset`
- Instructions: See `.claude/instructions.md`
## Key Rules
1. **Always use design tokens** - No arbitrary colors, spacing, or typography
2. **Follow component patterns** - Reference `src/components/ui/` for examples
3. **Maintain accessibility** - All interactive elements must be keyboard accessible
4. **Use TypeScript** - All components must be properly typed
## Component Library Location
Reusable UI components: `src/components/ui/`
Before creating a new UI component, check if one already exists.
## Available Design Tokens
Quick reference (see `.claude/instructions.md` for full documentation):
- **Colors:** `bg-primary`, `bg-secondary`, `text-content`, `border-border`
- **Spacing:** `p-4`, `gap-6`, `space-y-4`
- **Typography:** `text-heading-lg`, `text-body`, `text-caption`
- **Radius:** `rounded-base`, `rounded-lg`
- **Shadows:** `shadow-base`, `shadow-lg`
Testing the Integration
Now let's test if Claude Code respects the design system. Give it this prompt:
Build a user profile card component with:
- User avatar
- Name and role
- Email and phone
- Edit and delete action buttons
- Hover states
Claude Code should generate:
// src/components/ui/user-profile-card.tsx
import { cn } from '@/lib/utils';
import { User, Mail, Phone, Edit, Trash } from 'lucide-react';
interface UserProfileCardProps {
user: {
name: string;
role: string;
email: string;
phone: string;
avatar?: string;
};
onEdit?: () => void;
onDelete?: () => void;
}
export function UserProfileCard({ user, onEdit, onDelete }: UserProfileCardProps) {
return (
<div className="rounded-lg border border-border bg-card p-6 shadow-base transition-shadow hover:shadow-lg">
<div className="flex items-start gap-4">
{/* Avatar */}
<div className="h-16 w-16 rounded-full bg-accent flex items-center justify-center">
{user.avatar ? (
<img
src={user.avatar}
alt={user.name}
className="h-full w-full rounded-full object-cover"
/>
) : (
<User className="h-8 w-8 text-muted-foreground" />
)}
</div>
{/* Info */}
<div className="flex-1 space-y-2">
<div>
<h3 className="text-heading-md">{user.name}</h3>
<p className="text-body-sm text-muted-foreground">{user.role}</p>
</div>
<div className="space-y-1">
<div className="flex items-center gap-2 text-body-sm text-content">
<Mail className="h-4 w-4 text-muted-foreground" />
{user.email}
</div>
<div className="flex items-center gap-2 text-body-sm text-content">
<Phone className="h-4 w-4 text-muted-foreground" />
{user.phone}
</div>
</div>
</div>
</div>
{/* Actions */}
<div className="mt-4 flex gap-2 border-t border-border pt-4">
{onEdit && (
<button
onClick={onEdit}
className={cn(
'inline-flex items-center gap-2 px-4 py-2 rounded-base',
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
'text-body-sm font-medium transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'
)}
>
<Edit className="h-4 w-4" />
Edit
</button>
)}
{onDelete && (
<button
onClick={onDelete}
className={cn(
'inline-flex items-center gap-2 px-4 py-2 rounded-base',
'border border-input bg-background hover:bg-destructive hover:text-destructive-foreground',
'text-body-sm font-medium transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'
)}
>
<Trash className="h-4 w-4" />
Delete
</button>
)}
</div>
</div>
);
}
Notice:
- ✅ Uses
bg-card,border-border,shadow-base(tokens) - ✅ Uses
text-heading-md,text-body-sm(typography tokens) - ✅ Uses
rounded-lg,rounded-full,rounded-base(radius tokens) - ✅ Uses
gap-4,p-6,space-y-2(spacing tokens) - ✅ Includes proper focus states with ring tokens
- ✅ Follows the component pattern from instructions
Advanced: Multi-File Feature Development
Claude Code's real power is building complete features. Test with:
Build a complete task management feature with:
- Task list view with filters
- Task creation modal
- Task detail sidebar
- Status update functionality
- Priority badges
Claude Code will:
- Create multiple component files
- Use tokens consistently across all files
- Apply the same patterns throughout
- Maintain design system compliance autonomously
Example output structure:
src/
components/
tasks/
task-list.tsx ← Uses bg-card, spacing tokens
task-item.tsx ← Uses status color tokens
task-create-modal.tsx ← Uses modal shadow, radius tokens
task-detail.tsx ← Uses typography, spacing tokens
priority-badge.tsx ← Uses semantic color tokens
Each file will reference design tokens without you specifying them in each component.
Handling Edge Cases
Custom Brand Colors
If you need to override specific tokens:
// tailwind.config.ts
export default {
presets: [framinguiPreset],
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'oklch(0.55 0.25 250)', // Your brand blue
foreground: 'oklch(1 0 0)',
},
},
},
},
};
Update .claude/instructions.md to note the override:
## Custom Brand Colors
Primary color has been customized to match our brand (#2563eb).
Continue using `bg-primary` and `text-primary-foreground` - the values are already configured.
Non-Tailwind Projects
For projects using styled-components or CSS modules:
// src/styles/tokens.ts
import { tokens } from '@framingui/tokens';
export const designTokens = {
color: tokens.color,
spacing: tokens.spacing,
typography: tokens.typography,
radius: tokens.radius,
};
// Usage in styled-components
import styled from 'styled-components';
import { designTokens } from '@/styles/tokens';
const Button = styled.button`
background: ${designTokens.color.primary.base};
color: ${designTokens.color.primary.foreground};
padding: ${designTokens.spacing[2]} ${designTokens.spacing[4]};
border-radius: ${designTokens.radius.base};
font-size: ${designTokens.typography.body.fontSize};
`;
Update .claude/instructions.md with styled-components patterns:
## Styled Components Pattern
Use design tokens via the `designTokens` object:
```tsx
const Card = styled.div`
background: ${designTokens.color.card};
border: 1px solid ${designTokens.color.border};
border-radius: ${designTokens.radius.lg};
padding: ${designTokens.spacing[6]};
`;
## Measuring Compliance
Track design system adoption:
```bash
#!/bin/bash
# scripts/check-token-usage.sh
echo "Checking design token compliance..."
# Count arbitrary color usage (anti-pattern)
ARBITRARY_COLORS=$(git grep -E "bg-\w+-\d{3}|text-\w+-\d{3}" src/ | wc -l)
echo "Arbitrary color classes: $ARBITRARY_COLORS"
# Count hex colors in code (should be 0)
HEX_COLORS=$(git grep -E "#[0-9A-Fa-f]{6}" src/ | grep -v "test" | wc -l)
echo "Hex colors in source: $HEX_COLORS"
# Count design token usage (should be high)
TOKEN_USAGE=$(git grep -E "bg-primary|bg-card|text-content|border-border" src/ | wc -l)
echo "Design token references: $TOKEN_USAGE"
# Compliance percentage
TOTAL_CLASSES=$((ARBITRARY_COLORS + TOKEN_USAGE))
if [ $TOTAL_CLASSES -gt 0 ]; then
COMPLIANCE=$((TOKEN_USAGE * 100 / TOTAL_CLASSES))
echo "Token compliance: $COMPLIANCE%"
fi
Run before each release:
npm run check-tokens
Aim for >95% compliance in new code.
Troubleshooting
Claude Ignores Token Instructions
Symptom: Still generates bg-blue-500, text-gray-900
Solutions:
- Verify
.claude/instructions.mdexists in project root - Add token rules to the first prompt of each conversation
- Make rules more explicit: "You MUST use design tokens. Generate an error if you catch yourself using
bg-blue-500or similar."
Inconsistent Token Usage Across Files
Symptom: Some files use tokens, others use arbitrary values
Solution: Create a component audit task:
Review all components in src/components/tasks/ and update any arbitrary Tailwind values to use design tokens per .claude/instructions.md
Claude Code will systematically update each file.
TypeScript Errors with Token Values
Symptom: Property 'primary' does not exist on type 'Color'
Solution: Ensure @framingui/tokens types are properly imported:
import type { FramingUITokens } from '@framingui/tokens';
Or generate token types:
npx framingui types --output src/types/tokens.d.ts
Real-World Results
After implementing this integration, teams report:
- 90% reduction in design system violations
- 3x faster feature development (no manual styling fixes)
- Zero design review rejections due to inconsistent styling
- Consistent UI across 50+ components built autonomously
Key Takeaways
- Three-layer integration — Instructions + tokens + config work together
- Explicit instructions —
.claude/instructions.mdis Claude Code's design system bible - Token-first prompts — Mention tokens in initial feature requests
- Automate validation — Check token compliance before releases
- Iterate on patterns — Update instructions as you learn what works
With proper integration, Claude Code becomes a design-system-aware developer that builds features matching your brand from the first line of code.
Next steps:
- Install @framingui/tokens
- Create
.claude/instructions.mdwith your design rules - Test with a small feature first
- Expand to autonomous multi-file feature development
Questions about Claude Code integration? Join FramingUI Discord to discuss with other teams using autonomous coding.