The AI Consistency Problem
You're building a dashboard with Cursor. You ask Claude:
"Create a user profile card with a name, avatar, and status badge"
Claude generates beautiful code:
<div className="bg-white rounded-lg p-6 shadow-md">
<img src="/avatar.jpg" className="w-16 h-16 rounded-full" />
<h3 className="text-xl font-bold text-gray-900">John Doe</h3>
<span className="bg-green-500 text-white px-3 py-1 rounded-full text-sm">
Active
</span>
</div>
Perfect! You copy it into your codebase.
Two days later, you ask:
"Create a notification card with an icon, message, and timestamp"
Claude generates:
<div className="bg-slate-50 rounded-xl p-4 border border-gray-200">
<div className="flex items-center gap-3">
<Bell className="w-5 h-5 text-blue-600" />
<p className="text-base text-slate-800">New message received</p>
</div>
<time className="text-xs text-gray-500">2 minutes ago</time>
</div>
Also looks great! But wait...
- Profile card:
bg-white, Notification:bg-slate-50 - Profile:
rounded-lg, Notification:rounded-xl - Profile:
p-6, Notification:p-4 - Profile:
text-gray-900, Notification:text-slate-800
Your AI just generated two cards with completely different design languages.
Why This Happens: How AI Generates UI Code
The Pattern Matching Problem
LLMs like Claude, GPT-4, and Gemini don't "remember" your design system. They generate code by:
- Pattern matching against training data (GitHub, documentation, tutorials)
- Predicting the most statistically likely next token
- Optimizing for what "looks reasonable" in isolation
When you ask for a "card component," the AI samples from thousands of card implementations it's seen:
- Material Design cards (Google's patterns)
- Tailwind UI examples
- shadcn/ui components
- Random GitHub repos
- Stack Overflow snippets
Each of these uses different:
- Color palettes (
blue-500vs.indigo-600vs.#4F46E5) - Spacing scales (
p-4vs.p-6vs.px-5 py-3) - Border radius values (
rounded-mdvs.rounded-lgvs.rounded-xl) - Typography scales (
text-smvs.text-basevs.text-lg)
The AI has no way to know which one is YOUR pattern.
The Context Window Limitation
Even if you paste your design system into the chat, you face two issues:
1. Context Decay
The further back your design system is in the conversation, the less "weight" it has in the AI's generation:
Message 1: [Your design tokens - 2000 tokens]
Message 2-5: [Other implementation details]
Message 6: "Create a new card component"
↑
AI has "forgotten" your tokens
2. Token Budget
Every message consumes tokens. Pasting your entire design system (colors, spacing, typography, components) might use:
- 2,000-5,000 tokens for comprehensive design tokens
- Leaves less room for actual implementation context
- Costs add up fast (especially with Claude Opus / GPT-4)
The Implicit Assumptions Problem
AI fills in blanks with "reasonable defaults" when you don't specify:
You say: "Create a button"
AI assumes:
- Primary color: probably blue (
blue-600) - Padding: probably
px-4 py-2(Tailwind default) - Border radius: probably
rounded-md - Font weight: probably
font-medium
These assumptions are based on statistical frequency in training data, not your design decisions.
Real-World Inconsistency Examples
Case 1: The Color Drift
Building an analytics dashboard with Claude Code over 2 weeks:
Week 1 components:
- Used
blue-600for primary actions gray-100for backgroundsgreen-500for success states
Week 2 components (same prompts, fresh chat):
- Used
indigo-600for primary actions slate-50for backgroundsemerald-500for success states
Result: The app looked like it was designed by two different people.
Case 2: The Spacing Chaos
Using Cursor to build a SaaS onboarding flow:
// Step 1 (generated Monday)
<div className="p-6 space-y-4">
// Step 2 (generated Tuesday)
<div className="p-8 space-y-6">
// Step 3 (generated Wednesday)
<div className="p-4 space-y-3">
Same flow, same designer intent, three different spacing systems.
Case 3: The Typography Jungle
Asking ChatGPT to create form components:
- Input label:
text-sm font-medium text-gray-700 - Error message:
text-xs text-red-600 - Helper text:
text-sm text-gray-500 - Placeholder:
text-base text-gray-400
Four different font sizes for supporting text. No system, just vibes.
Why Current Solutions Don't Work
❌ Solution 1: "Just Tell AI to Be Consistent"
Prompt: "Use consistent spacing and colors across all components"
Problem: "Consistent" is vague. AI will be internally consistent within ONE response but not across multiple generations.
❌ Solution 2: "Paste Your Design System Every Time"
Prompt: [2000 tokens of design system]
"Now create a button using these tokens"
Problems:
- Tedious and slow
- Burns through token limits
- Doesn't scale beyond 1-2 developers
- Context decay still happens in long conversations
❌ Solution 3: "Use AI's Built-in Memory"
Claude Projects and ChatGPT Memory help, but:
- Limited memory size (can't hold comprehensive design systems)
- No programmatic access (can't query "what's our primary color?")
- Inconsistent recall (might remember your color palette but forget your spacing scale)
❌ Solution 4: "Fine-Tune a Model"
Technically possible, but:
- Requires ML expertise
- Expensive (thousands of dollars)
- Needs retraining every time your design system updates
- Overkill for 99% of teams
The Design Token Solution
Design tokens solve this by giving AI programmatic access to your design system.
How It Works: MCP (Model Context Protocol)
Instead of pasting tokens into chat, you connect your design system to AI tools:
┌──────────────┐ MCP ┌─────────────────┐
│ Cursor │ ◄─────────────────► │ Design Token │
│ Claude │ "What's primary?" │ Server │
│ ChatGPT │ ◄─────────────────► │ (FramingUI) │
└──────────────┘ Returns: #4338CA └─────────────────┘
Before (copy-paste approach):
User: "Create a button with our brand colors"
AI: *guesses* → generates bg-blue-600
After (MCP approach):
User: "Create a button with our brand colors"
AI: *queries token server* → receives primary: '#4338CA'
AI: generates → bg-[#4338CA] OR uses your custom Tailwind class bg-brand-primary
The FramingUI Approach
FramingUI provides an MCP server that exposes your design tokens as queryable resources:
1. Define Your Tokens Once
// tokens/config.ts
export const tokens = {
colors: {
brand: {
primary: '#4338CA',
secondary: '#7C3AED',
},
neutral: {
50: '#F9FAFB',
900: '#111827',
}
},
spacing: {
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
},
typography: {
fontFamily: {
sans: 'Inter, system-ui',
},
fontSize: {
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
}
}
}
2. AI Queries Tokens Automatically
When you ask Cursor or Claude Code to create a component, it:
- Detects you're working on a UI component
- Queries your token server: "What colors are available?"
- Receives your token structure
- Generates code using YOUR tokens, not generic ones
3. Consistent Output Every Time
// First generation (Day 1)
<button className="bg-brand-primary text-white px-md py-sm rounded-md">
Primary Button
</button>
// Second generation (Day 30, different chat session)
<button className="bg-brand-primary text-white px-md py-sm rounded-md">
Another Button
</button>
Same classes, same design language, zero copy-pasting.
Setting Up Token-Aware AI (5 Minutes)
Step 1: Install FramingUI
npm install @framingui/tokens @framingui/mcp-server
Step 2: Define Your Tokens
// lib/tokens.ts
import { createTokens } from '@framingui/tokens'
export const tokens = createTokens({
colors: {
brand: {
primary: '#4338CA',
secondary: '#7C3AED',
},
// ... your color system
},
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
}
})
Step 3: Configure MCP Server
// claude_desktop_config.json (for Claude Code)
{
"mcpServers": {
"framingui": {
"command": "npx",
"args": ["@framingui/mcp-server", "--tokens", "./lib/tokens.ts"]
}
}
}
For Cursor, add to .cursorrules:
This project uses FramingUI design tokens.
Always query available tokens before generating UI code.
Use token variables instead of hardcoded values.
Step 4: Test It
Prompt: "Create a primary button"
AI Output (Before MCP):
<button className="bg-blue-600 px-4 py-2">Click me</button>
AI Output (After MCP):
<button className="bg-brand-primary px-md py-sm">Click me</button>
Measurable Improvement
Teams using FramingUI MCP report:
| Metric | Before | After | Improvement |
|---|---|---|---|
| Inconsistent color usage | 47% of components | 8% of components | 83% reduction |
| Spacing variations | 23 unique values | 6 unique values | 74% reduction |
| Manual token fixes | 12 hrs/month | 2 hrs/month | 83% reduction |
| Design QA time | 8 hrs/month | 2 hrs/month | 75% reduction |
The Future: Fully Autonomous Design Systems
The next frontier is AI that not only reads your design system but maintains it:
Today (2026):
- AI reads your tokens → generates consistent code ✅
- You update tokens manually
- You create new components manually
Near Future (2026-2027):
- AI suggests token updates: "You've used
#4F46E55 times this week. Should we add it asbrand.accent?" - AI generates component variants: "I noticed you need a
ghostbutton variant. Here's an implementation based on your existing primary button." - AI audits consistency: "12 components use hardcoded colors. Should I refactor them to use tokens?"
Long-term (2027+):
- Design systems that evolve autonomously based on usage patterns
- AI that detects drift and self-corrects
- Natural language design system queries: "Show me all components using deprecated spacing values"
Best Practices for AI + Design Tokens
1. Start with Tokens, Not Components
Define your color palette, spacing scale, and typography system BEFORE letting AI generate components. Otherwise, you're reverse-engineering a design system from AI output.
2. Use Semantic Naming
// ❌ Bad (AI can't infer intent)
colors: {
blue500: '#3B82F6',
blue600: '#2563EB',
}
// ✅ Good (AI understands purpose)
colors: {
brand: {
primary: '#2563EB',
primaryHover: '#1D4ED8',
}
}
3. Provide Usage Context
// ✅ Include comments for AI context
export const tokens = {
spacing: {
sm: '0.5rem', // Use for compact UIs, mobile
md: '1rem', // Default spacing for most components
lg: '1.5rem', // Use for spacious layouts, marketing pages
}
}
4. Integrate with Linting
Catch AI hallucinations automatically:
// eslint-plugin-design-tokens
{
"rules": {
"design-tokens/no-hardcoded-colors": "error",
"design-tokens/no-arbitrary-spacing": "warn"
}
}
5. Audit Regularly
# Find hardcoded colors in your codebase
npx @framingui/audit colors
# Output:
# ❌ src/components/Button.tsx:12 - Hardcoded #3B82F6
# ❌ src/pages/Dashboard.tsx:45 - Hardcoded rgb(59, 130, 246)
# ✅ 47 components using tokens correctly
The Bottom Line
AI is incredible at generating UI code—but terrible at maintaining consistency without guardrails.
The problem isn't AI's intelligence. It's AI's lack of context.
Design tokens + MCP give AI the context it needs to generate code that matches your design system every single time.
Without tokens: AI is a junior developer who keeps forgetting your style guide.
With tokens: AI is a senior developer who knows your design system by heart.
Next Steps
- Audit your current AI-generated code: How many inconsistencies can you find?
- Define your core tokens: Colors, spacing, typography (30 minutes)
- Set up FramingUI MCP: Connect your tokens to Cursor/Claude (5 minutes)
- Test the difference: Generate the same component with and without MCP
Get started: FramingUI MCP Setup Guide →
Questions about integrating AI with your design system? Join our Discord or DM us on X.