"Vibe coding" is the future: you describe what you want, and AI agents like Claude Code or Cursor build it. No wrestling with CSS. No debugging responsive layouts. Just high-level intent, translated to working code.
But there's a hidden cost. Without design constraints, vibe coding produces visually inconsistent interfaces that don't scale.
This post explains why design systems are essential for AI-generated code—and how to implement them without slowing down your flow.
What is Vibe Coding?
Vibe coding is prompt-driven development. Instead of writing every line yourself, you give the AI high-level instructions:
"Build a user settings page with profile photo upload, email preferences, and a save button"
The AI generates the components, routing, and state management. You review, tweak, and ship.
The Promise
- Speed: Features in minutes, not hours
- Focus: Spend time on logic, not layout
- Accessibility: AI knows ARIA patterns better than most developers
The Problem
- Inconsistent styling: Every component gets arbitrary colors, spacing, shadows
- No cohesion: Login page uses
blue-600, dashboard usesindigo-500 - Scaling nightmare: 50 components, 50 different interpretations of "primary button"
The Visual Debt Problem
Traditional codebases accumulate technical debt. AI-generated codebases accumulate visual debt.
Example: Button Styles
Without constraints, AI generates buttons like this:
Login page:
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg">
Sign In
</button>
Dashboard:
<button className="px-6 py-3 bg-indigo-500 text-white rounded-md shadow-sm">
Save Changes
</button>
Settings page:
<button className="px-5 py-2.5 bg-blue-700 text-white rounded">
Update Profile
</button>
Three buttons, three different:
- Padding scales (
px-4/py-2,px-6/py-3,px-5/py-2.5) - Colors (
blue-600,indigo-500,blue-700) - Border radii (
rounded-lg,rounded-md,rounded)
Each choice is reasonable in isolation. Together, they create visual chaos.
Why AI Generates Inconsistent UI
AI models are trained on millions of codebases with different design languages. When you ask for a "primary button," the model samples from this distribution:
- Material Design patterns (Google)
- Tailwind examples (common in docs)
- Bootstrap conventions (legacy web)
- Custom component libraries (GitHub repos)
Without explicit constraints, the model makes statistically common choices, not your design choices.
The Averaging Problem
AI doesn't know that your brand uses:
#2563ebfor primary actions (not#3b82f6)- 8px border radius (not 4px or 6px)
- 16px/24px vertical spacing (not 12px or 20px)
It guesses based on training data. And guesses vary.
Design Systems as AI Constraints
A design system is a set of rules that AI follows during generation. Instead of:
"Create a button"
You provide:
"Create a button using
var(--color-interactive-primary)for background,var(--spacing-component-sm)for padding, andvar(--border-radius-md)for corners"
But typing that every time defeats the purpose of vibe coding.
Solution: Embed Design Tokens
Instead of repeating constraints in every prompt, define them once and make them available to the AI:
1. Create a design token file:
{
"color": {
"interactive-primary": "#2563eb",
"interactive-hover": "#1d4ed8"
},
"spacing": {
"component-sm": "0.75rem",
"component-md": "1rem"
},
"border-radius": {
"md": "0.5rem"
}
}
2. Reference it in Claude Code instructions (.claude/instructions.md):
All components must use design tokens from `design-tokens.json`.
Never use hardcoded Tailwind utilities like `bg-blue-600` or `p-4`.
Always reference tokens: `bg-[var(--color-interactive-primary)]`.
Now every component AI generates follows your design system—without you specifying values in each prompt.
Real-World Example: Dashboard Redesign
Before: Vibe Coding Without Constraints
Prompt:
"Create a dashboard with stats cards showing users, revenue, and growth"
Generated code:
<div className="grid grid-cols-3 gap-6">
<div className="p-6 bg-white rounded-lg shadow">
<p className="text-sm text-gray-600">Total Users</p>
<p className="text-3xl font-bold text-gray-900">1,234</p>
</div>
<div className="p-5 bg-gray-50 rounded-md border border-gray-200">
<p className="text-xs text-gray-500">Revenue</p>
<p className="text-2xl font-semibold text-gray-800">$12,345</p>
</div>
<div className="p-4 bg-blue-50 rounded border-2 border-blue-200">
<p className="text-sm text-blue-600">Growth</p>
<p className="text-4xl font-bold text-blue-900">+23%</p>
</div>
</div>
Problems:
- Inconsistent padding (
p-6,p-5,p-4) - Inconsistent backgrounds (
bg-white,bg-gray-50,bg-blue-50) - Inconsistent typography (
text-3xl,text-2xl,text-4xl) - Inconsistent borders (shadow, border, border-2)
After: Vibe Coding With Design Tokens
Same prompt, with design system configured:
Generated code:
<div className="grid grid-cols-3 gap-[var(--spacing-layout-md)]">
<div className="p-[var(--spacing-component-md)]
bg-[var(--color-surface-elevated)]
rounded-[var(--border-radius-md)]
border border-[var(--color-border-subtle)]">
<p className="text-[var(--typography-caption-size)]
text-[var(--color-text-secondary)]">
Total Users
</p>
<p className="text-[var(--typography-heading-1-size)]
font-[var(--typography-heading-1-weight)]
text-[var(--color-text-primary)]">
1,234
</p>
</div>
{/* Remaining cards follow same pattern */}
</div>
Benefits:
- All cards use identical spacing, colors, typography
- Switching to dark mode updates all tokens centrally
- Rebranding changes one file, not 50 components
How to Implement Design Systems for Vibe Coding
1. Define Core Tokens
Start with the minimum:
- Colors: text, backgrounds, borders, interactive states
- Spacing: component padding, layout gaps
- Typography: heading sizes, body text, captions
2. Convert to CSS Variables
Generate tokens.css:
:root {
--color-text-primary: #1a1a1a;
--color-interactive-primary: #2563eb;
--spacing-component-md: 1rem;
--typography-heading-1-size: 2.25rem;
}
3. Configure AI Instructions
In .claude/instructions.md:
## Design System Rules
1. Use semantic tokens for all styling
2. Never use hardcoded colors or spacing
3. Reference tokens via CSS variables: `var(--token-name)`
## Token Categories
- Colors: `var(--color-*)`
- Spacing: `var(--spacing-*)`
- Typography: `var(--typography-*)`
4. Verify Consistency
Generate a few components and check:
- Are all buttons using the same color token?
- Do all cards use the same padding token?
- Is typography consistent across components?
If not, refine your instructions to be more explicit.
Advanced: MCP for Persistent Context
If you're using Claude Code with MCP (Model Context Protocol), serve design tokens as a persistent resource:
// mcp-server-design-tokens/index.ts
server.resource({
uri: 'design://tokens',
name: 'Design Tokens',
mimeType: 'application/json',
async get() {
return JSON.stringify(tokens);
}
});
Now every Claude Code session has instant access to your design system without injecting it into prompts.
Common Objections
"Design systems slow down iteration"
True for manual development. Not true for AI.
With AI, the iteration speed is the same whether you use tokens or hardcoded values. But with tokens, you iterate on consistent UI. Without them, you iterate on chaos.
"I'll fix styling later"
Visual debt compounds faster than technical debt.
After generating 20 components with arbitrary styles, refactoring them to use tokens takes hours. Defining tokens upfront takes 30 minutes.
"AI should just know my design preferences"
AI models don't remember across sessions. Every new conversation starts fresh.
Unless you embed preferences as persistent context (via MCP or instructions), the AI guesses every time.
Key Takeaways
- Vibe coding is powerful but chaotic without design constraints
- Design tokens provide structure AI can follow consistently
- Define tokens once, reference them in all AI-generated components
- Visual debt scales faster in AI development than traditional coding
- MCP makes design systems persistent across all sessions
Conclusion
Vibe coding is not just fast—it's the future of how we build software. But speed without structure creates technical and visual debt that's expensive to fix.
Design systems are the missing layer between AI code generation and production-quality interfaces. They don't slow you down. They ensure the code AI generates today still makes sense six months from now.
Next Steps:
- Set up FramingUI with Claude Code
- Learn about AI Agent UI Patterns
- Explore MCP Design System Server