Tutorial

Shadcn UI + AI: The Missing Piece

How FramingUI fills the gap between shadcn UI and AI code generation with design tokens and consistent styling.

FramingUI Team3 min read

The Problem with AI + Shadcn UI

Shadcn UI is fantastic for human developers — you copy components, paste them into your project, and customize as needed. But when AI tools like Claude Code or Cursor generate UI code, they face a critical challenge: how do you ensure consistency across hundreds of generated components?

AI can hallucinate color values, spacing, and styling patterns that don't match your design system. One component might use bg-blue-500, another bg-indigo-600, and a third #4F46E5 — all intended to be your "primary" color.

FramingUI: The Missing Bridge

FramingUI solves this by forking shadcn UI and integrating design tokens directly into every component. Instead of arbitrary Tailwind classes, every style references a semantic token:

// ❌ Shadcn UI (original)
<button className="bg-blue-500 hover:bg-blue-600 text-white">
  Click me
</button>

// ✅ FramingUI (token-powered)
<Button variant="default">
  Click me
</Button>

// Under the hood:
// bg-[var(--tekton-bg-primary)]
// hover:bg-[var(--tekton-bg-primary)]/90

Real-World Example: Button Component

Here's how FramingUI's Button component uses tokens:

import { Button } from '@framingui/ui';

function LoginForm() {
  return (
    <div className="space-y-[var(--tekton-spacing-4)]">
      <Button variant="default">Sign In</Button>
      <Button variant="outline">Create Account</Button>
      <Button variant="destructive">Delete</Button>
    </div>
  );
}

Every button automatically inherits your theme's colors, spacing, and border radius — zero hardcoded values.

How Design Tokens Prevent AI Hallucination

When AI generates code using FramingUI, it can't hallucinate colors because:

  1. Single source of truth: All colors come from var(--tekton-*) tokens
  2. Semantic naming: --tekton-bg-primary is unambiguous
  3. OKLCH foundation: Colors are perceptually uniform, ensuring consistent brightness

Example: AI-Generated Card

import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@framingui/ui';

// AI-generated component using FramingUI
function ProductCard({ title, description, price }: ProductCardProps) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>{title}</CardTitle>
        <CardDescription>{description}</CardDescription>
      </CardHeader>
      <CardContent>
        <p className="text-2xl font-bold text-[var(--tekton-bg-primary)]">
          ${price}
        </p>
      </CardContent>
    </Card>
  );
}

Notice how the AI uses tokens (var(--tekton-bg-primary)) instead of guessing text-blue-600 or #3B82F6.

OKLCH: The Secret Sauce

FramingUI uses OKLCH color space for design tokens, which provides:

  • Perceptual uniformity: L=0.5 looks equally bright across all hues
  • Wider gamut: Access to more vibrant colors than sRGB
  • WCAG compliance: Easier to hit AA/AAA contrast ratios

Traditional color spaces like HSL fail here — hsl(220, 100%, 50%) (blue) looks darker than hsl(60, 100%, 50%) (yellow) despite both having 50% lightness.

Integration with AI Tools

Cursor IDE Setup

# Install FramingUI
pnpm add @framingui/ui @framingui/core

# Generate design tokens from your brand color
npx framingui generate --color "#FF6B35"

Then add this to your Cursor rules (.cursorrules):

When generating UI components:
- Always import from @framingui/ui
- Use var(--tekton-*) tokens for colors, spacing, and radius
- Never hardcode color values or spacing

Claude Code Setup

Create a .claude/skills/framingui.md file:

## FramingUI Component Library

Import components from @framingui/ui:
- Button, Input, Card, Form, Dialog, etc.

Design tokens (use these instead of Tailwind colors):
- Colors: var(--tekton-bg-primary), var(--tekton-bg-secondary)
- Spacing: var(--tekton-spacing-2), var(--tekton-spacing-4)
- Radius: var(--tekton-radius-md), var(--tekton-radius-lg)

Migration from Shadcn UI

Already using shadcn UI? FramingUI is a drop-in replacement:

// Before (shadcn)
import { Button } from '@/components/ui/button';

// After (FramingUI)
import { Button } from '@framingui/ui';
// Same API, token-powered internals

Next Steps

  1. Try the playground: Visit framingui.com to generate your design tokens
  2. Install FramingUI: pnpm add @framingui/ui
  3. Configure your AI: Add FramingUI rules to Cursor or Claude Code
  4. Generate UI: Let AI create components with 0% hallucination

FramingUI gives AI the constraints it needs to generate consistent, production-ready UI — bridging the gap between shadcn UI's flexibility and AI's need for structure.

Ready to build with FramingUI?

Join the beta and get early access to agentic design systems that adapt to your needs.

Join Beta
Share

Related Posts