Guide

AI Coding Without Design Skills: How to Build Professional UIs

You don't need to be a designer to build good-looking UIs with AI. Learn how design tokens bridge the gap between code and design.

FramingUI Team10 min read

You're a developer, not a designer. You can build complex backend systems, optimize database queries, and debug race conditions. But when it's time to build UI, you freeze.

What color should this button be? How much padding? What font size? Which shade of gray for the text?

You try your best. Maybe you copy styles from a reference site. Maybe you ask AI to "make it look good." The result? It works, but it doesn't look professional. And you know it.

This isn't a design skills problem. It's a design constraints problem. You don't need to become a designer—you need a system that makes design decisions for you.

The Non-Designer's UI Problem

When designers build UI, they work from a system:

Brand color → Primary action color
Spacing scale → Component padding
Typography scale → Text sizes
Semantic colors → Success/error states

When non-designers build UI without a system, every choice is arbitrary:

"This blue looks good" → #3B82F6
"Needs some padding" → padding: 12px
"Should be bigger" → font-size: 18px
"Needs to be red" → color: #DC2626

Six months later, you have:

  • 12 different shades of blue
  • Spacing values from 8px to 22px
  • Font sizes ranging from 13px to 19px
  • No consistent visual language

The code works. The design is chaos.

Why AI Doesn't Solve This Alone

You might think: "I'll just ask Claude/Cursor to make it look good."

Here's what happens:

You: "Create a user dashboard"

AI generates:

<div className="bg-white rounded-lg shadow-md p-6">
  <h1 className="text-2xl font-bold text-gray-900 mb-4">Dashboard</h1>
  <div className="grid grid-cols-3 gap-4">
    <div className="bg-blue-50 border border-blue-200 rounded p-4">
      <p className="text-sm text-gray-600">Total Users</p>
      <p className="text-3xl font-semibold text-gray-900">1,234</p>
    </div>
    {/* more stats */}
  </div>
</div>

It looks... fine. Generic, but fine.

Then you ask it to create a settings page:

<div className="max-w-2xl mx-auto bg-white shadow rounded-lg p-8">
  <h2 className="text-xl font-semibold text-gray-800 mb-6">Settings</h2>
  <form className="space-y-6">
    <button className="bg-indigo-600 text-white px-6 py-2 rounded-md">
      Save Changes
    </button>
  </form>
</div>

Wait. The dashboard used text-2xl for headings, settings uses text-xl. Dashboard used blue-50, settings uses indigo-600. Dashboard has mb-4 spacing, settings has mb-6.

AI doesn't remember your design decisions across conversations. Each component uses different values. Your UI becomes inconsistent.

The Solution: Design Tokens as Constraints

Design tokens are pre-defined design decisions. Instead of making up values, you reference token names:

// Without tokens (arbitrary decisions)
<button className="bg-blue-600 text-white px-4 py-2 rounded">
  Click me
</button>

// With tokens (system decisions)
<button className="bg-primary text-primary-foreground px-4 py-2 rounded-base">
  Click me
</button>

The difference:

  • bg-blue-600 is arbitrary—could be any blue
  • bg-primary is semantic—it's your brand color, defined once

When AI generates code with tokens, it can't make arbitrary decisions. It must use the system.

How Tokens Work for Non-Designers

Think of design tokens like a variable system for design:

Colors

Instead of:

// Which blue? How do I pick?
bg-blue-500  // This one?
bg-blue-600  // Or this?
bg-sky-500   // Or this?

Use semantic names:

bg-primary        // Brand color (automatically consistent)
bg-secondary      // Secondary brand color
bg-accent         // Accent color
bg-success        // Success states (green)
bg-destructive    // Danger/delete actions (red)

You never pick a color. The system defines it.

Spacing

Instead of:

// Random padding values
p-[12px]  // Why 12?
p-[14px]  // Why 14?
p-[16px]  // Why 16?

Use a scale:

p-2   // 0.5rem (small)
p-4   // 1rem (medium, most common)
p-6   // 1.5rem (large)
p-8   // 2rem (extra large)

The scale is predefined. You just pick the size relative to other elements.

Typography

Instead of:

// What size should headings be?
text-xl      // Is this big enough?
text-2xl     // Too big?
text-[22px]  // Custom size?

Use semantic text styles:

text-heading-lg    // Large headings
text-heading-md    // Medium headings
text-body          // Body text
text-caption       // Small text, captions

Each style has font-size, line-height, and font-weight defined.

Border Radius

Instead of:

rounded      // Too round?
rounded-md   // Not round enough?
rounded-lg   // Just right?

Use semantic radius values:

rounded-base    // Default for buttons, inputs
rounded-lg      // Cards, modals
rounded-full    // Avatars, pills

Real Example: Building a Login Form

Here's how a non-designer builds a login form with vs without tokens:

Without Tokens (Arbitrary Decisions)

function LoginForm() {
  return (
    <div className="max-w-md mx-auto mt-20 bg-white p-8 rounded-lg shadow-lg">
      <h2 className="text-2xl font-bold text-gray-900 mb-6">Sign In</h2>
      
      <form className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-1">
            Email
          </label>
          <input
            type="email"
            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-1">
            Password
          </label>
          <input
            type="password"
            className="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </div>
        
        <button className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700">
          Sign In
        </button>
      </form>
    </div>
  );
}

Questions you had to answer:

  • What's the right heading size? (picked text-2xl)
  • What gray for labels? (picked text-gray-700)
  • What border color? (picked border-gray-300)
  • What blue for buttons? (picked bg-blue-600)
  • What shadow? (picked shadow-lg)
  • What focus ring color? (picked ring-blue-500)

Every decision was a guess.

With Tokens (System Decisions)

function LoginForm() {
  return (
    <div className="max-w-md mx-auto mt-20 bg-card p-8 rounded-lg border border-border shadow-base">
      <h2 className="text-heading-lg mb-6">Sign In</h2>
      
      <form className="space-y-4">
        <div>
          <label className="block text-label mb-1">
            Email
          </label>
          <input
            type="email"
            className="w-full px-3 py-2 border border-input rounded-base bg-background text-content focus:outline-none focus:ring-2 focus:ring-ring"
          />
        </div>
        
        <div>
          <label className="block text-label mb-1">
            Password
          </label>
          <input
            type="password"
            className="w-full px-3 py-2 border border-input rounded-base bg-background text-content focus:outline-none focus:ring-2 focus:ring-ring"
          />
        </div>
        
        <button className="w-full bg-primary text-primary-foreground py-2 rounded-base hover:bg-primary/90">
          Sign In
        </button>
      </form>
    </div>
  );
}

Decisions the system made for you:

  • Heading size → text-heading-lg
  • Label color → text-label
  • Border color → border-input
  • Button color → bg-primary
  • Shadow → shadow-base
  • Focus ring → ring-ring

You focused on structure. The system handled design.

Setting Up Design Tokens (For Non-Designers)

You don't need to create a design system from scratch. Use FramingUI's pre-built tokens:

Step 1: Install

npm install @framingui/tokens @framingui/tailwind-preset

Step 2: Configure Tailwind

Update tailwind.config.js:

import { framinguiPreset } from '@framingui/tailwind-preset';

export default {
  presets: [framinguiPreset],
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
};

That's it. Now you have access to 450+ design tokens.

Step 3: Use Tokens in Components

Instead of guessing values, reference token names:

// Colors
bg-primary, bg-secondary, bg-accent
text-content, text-muted-foreground
border-border, border-input

// 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

Your IDE autocompletes these names. No design knowledge needed.

Teaching AI to Use Tokens

Create a .cursorrules or .clauderules file in your project:

# Design Rules for AI

When generating UI components:

1. **Always use design tokens**, never arbitrary values
2. Use `bg-primary` instead of `bg-blue-500`
3. Use `text-heading-lg` instead of `text-2xl`
4. Use `rounded-base` instead of `rounded-md`
5. Use `border-border` instead of `border-gray-300`

Reference these token categories:
- Colors: bg-primary, bg-card, text-content, border-border
- Spacing: p-{2,4,6,8}, gap-{2,4,6}, space-y-{2,4,6}
- Typography: text-heading-{lg,md,sm}, text-body, text-caption
- Radius: rounded-base, rounded-lg, rounded-full
- Shadows: shadow-base, shadow-lg

Now when you ask AI to build UI, it uses your system:

You: "Create a profile card component"

AI generates with tokens:

<div className="bg-card border border-border rounded-lg p-6 shadow-base">
  <h3 className="text-heading-md mb-2">John Doe</h3>
  <p className="text-body-sm text-muted-foreground">Software Engineer</p>
  <button className="mt-4 bg-primary text-primary-foreground px-4 py-2 rounded-base">
    View Profile
  </button>
</div>

Consistent with your design system, zero design decisions from you.

Common Non-Designer Questions

"How do I know which token to use?"

Use semantic names that match intent:

  • Primary action?bg-primary
  • Secondary action?bg-secondary
  • Delete/danger?bg-destructive
  • Success message?bg-success
  • Body text?text-content
  • Less important text?text-muted-foreground
  • Default card?bg-card

The name describes the purpose, not the color.

"What if I need a custom color?"

You probably don't. Design tokens cover 90% of use cases:

  • Primary/secondary brand colors
  • Success/warning/error states
  • Text in various contrasts
  • Borders and dividers
  • Backgrounds and surfaces

If you genuinely need something custom, ask a designer or use an AI color tool like Coolors to generate a palette, then add it to your tokens.

"Can I change token values later?"

Yes! That's the power of tokens. Change once, apply everywhere:

// tailwind.config.js
export default {
  presets: [framinguiPreset],
  theme: {
    extend: {
      colors: {
        primary: {
          DEFAULT: '#2563eb', // Change this
          foreground: '#ffffff',
        },
      },
    },
  },
};

Every component using bg-primary updates instantly.

"Is this only for Tailwind?"

No. FramingUI tokens work with any CSS approach:

CSS Variables:

.button {
  background: var(--color-primary);
  padding: var(--spacing-4);
  border-radius: var(--radius-base);
}

Styled Components:

import { tokens } from '@framingui/tokens';

const Button = styled.button`
  background: ${tokens.color.primary.base};
  padding: ${tokens.spacing[4]};
  border-radius: ${tokens.radius.base};
`;

Inline styles:

import { tokens } from '@framingui/tokens';

<button style={{
  background: tokens.color.primary.base,
  padding: tokens.spacing[4],
}}>
  Click me
</button>

Before & After: Real Projects

Before Tokens

Dashboard: 8 shades of blue, 5 heading sizes, 12 spacing values
Settings: 6 shades of gray, 4 button styles, arbitrary shadows
Profile: Different card styles, inconsistent borders, random padding

Result: Functional but unprofessional-looking UI

After Tokens

Dashboard: bg-primary, text-heading-lg, p-6
Settings: text-muted-foreground, shadow-base, gap-4
Profile: bg-card, border-border, rounded-lg

Result: Consistent, professional UI without design expertise

The Non-Designer's Advantage

Designers spend hours choosing colors, spacing, typography. You get a system that makes those decisions for you.

Designers use tools like Figma to maintain consistency. You get tokens that enforce consistency in code.

Designers iterate on visual language. You reference semantic names that adapt when the design changes.

You don't need design skills. You need design constraints.

Design tokens are those constraints.

Getting Started Checklist

  • Install @framingui/tokens and @framingui/tailwind-preset
  • Update tailwind.config.js with FramingUI preset
  • Create .cursorrules with token instructions
  • Build one component using only tokens
  • Compare it to your old arbitrary-value components
  • Refactor existing components to use tokens
  • Let AI generate new components with your token system

Within a week, you'll stop guessing at design values. The system decides for you.

Key Takeaways

  1. You don't need design skills — you need design constraints
  2. Tokens are pre-made decisions — colors, spacing, typography defined once
  3. AI can enforce tokens — with proper instructions, it uses your system
  4. Consistency comes from constraints — not from design expertise
  5. Focus on structure — let tokens handle the design

Build functional, professional-looking UIs without becoming a designer. That's the power of design tokens.


Next steps:

  • Install @framingui/tokens
  • Try building your next component with tokens
  • Let AI do the work while tokens ensure consistency

Questions? Join FramingUI Discord to connect with other developers building without design teams.

Ready to build with FramingUI?

Build consistent UI with AI-ready design tokens. No more hallucinated colors or spacing.

Try FramingUI
Share

Related Posts