GliaKitAll guides

Guide · 8 min read

How to make Cursor and Claude Code follow your design system

AI coding tools invent colors, spacing and components unless you stop them. Tokens, rules files and a component inventory that keep generated UI on brand.

By Dejan Veljanoski · Updated

Ask Cursor or Claude Code for a settings page and you will get one that works. It will also use a blue that exists nowhere else in your product, padding picked at random, and a fresh button component that duplicates the three you already have. The model is not being careless. It simply has no idea what your product looks like, so it falls back to the average of everything it has seen.

The fix is not a longer prompt every time. It is giving the tools the same source of truth your designers use, in a form they read on every request. That takes four pieces: tokens, a rules file, a component inventory and a habit of checking the output.

1. Put every visual decision in tokens

A model cannot reuse a decision that only lives in a Figma file or in someone’s head. Move colors, radius and type into CSS custom properties with semantic names that say what a value is for, not what it looks like: --primary, --muted-foreground, --border, never --violet-500 in a component.

app/globals.css

:root {
  --background: #f4f4f8;
  --foreground: #14141b;
  --primary: #7c5cff;        /* accents and text links */
  --primary-strong: #6f4bff; /* fills under white text (AA) */
  --border: #e4e4ec;
}

.dark {
  --background: #0a0a0f;
  --foreground: #ededf2;
  --border: #1f1f2a;
}

@theme inline {
  --color-primary: var(--primary);
  --color-primary-strong: var(--primary-strong);
  --color-border: var(--border);
}

With Tailwind v4 the @theme inline block turns each token into a utility (bg-primary-strong, border-border), so the cheapest thing for the model to write is also the correct one. Dark mode comes for free: the components never change, only the token values do. If your Figma variables use the same names, a designer and a model are now pointing at the same thing.

2. Write the rules down where the tool reads them

Cursor loads project rules from .cursor/rules/*.mdc. Each file has a short frontmatter that says when it applies. A design-system rule should apply to every UI file, always:

.cursor/rules/design-system.mdc

---
description: Design system tokens and component rules. Always apply when writing UI.
globs: ["src/**/*.tsx", "src/**/*.css"]
alwaysApply: true
---

# Design system

Compose, don't invent. Every visual decision is already made.

## Colors
- Semantic Tailwind tokens only: bg-background, bg-card, text-foreground,
  text-muted-foreground, border-border, bg-primary-strong.
- Never hardcode hex values in components.

## Radius
- Buttons and inputs: rounded-md. Cards and panels: rounded-lg.

## Components
- Import from @/components/ui/* before building anything new.

Keep it short and absolute. Models follow “never hardcode hex” far more reliably than “try to prefer tokens where possible”. Put screen-level conventions (where routes live, how a page header looks, where demo data goes) in a second file scoped with a narrower glob such as src/app/**/*.tsx and alwaysApply: false.

Claude Code reads the same rules

Claude Code loads CLAUDE.md from the project root. Rather than maintaining two copies, keep the conventions in one file (many teams use AGENTS.md, which other agents also read) and import it:

CLAUDE.md

@AGENTS.md

Now Cursor and Claude Code get the same instructions, and you only update one place when the system changes.

3. Give the model an inventory, not just rules

“Reuse existing components” only works if the model knows what exists. List them in the rules file, grouped the way your Figma file is, with the props that matter:

- Actions: Button (default, gradient, outline, secondary, ghost,
  destructive · sizes xs–xl), Chip
- Forms: Input, Textarea, Field (label / helper / error), Select,
  Combobox, Checkbox, Radio, Switch, DatePicker, FileUpload
- Data display: Card + CardHeader, StatCard (delta, sparkline),
  Table with sortable TH, AreaChart, Badge, Avatar
- Feedback: Alert, Toast, EmptyState, CircularProgress
- Overlays: Dialog, Sheet, DropdownMenu, Tooltip, CommandPalette

This one list removes most duplicate components. When the model sees that a StatCard with a sparkline already exists, it imports it instead of rebuilding a worse one.

4. Prompt with structure, not adjectives

“Make it modern and clean” gives the model nothing to check against. A good UI prompt names the route, the purpose, the components and where the data comes from, then points back at the rules:

prompts/new-screen.md

Add a new screen at /(app)/refunds called "Refunds".

Purpose: review and approve pending refund requests.

Content:
- PageHeader with eyebrow "Billing", title "Refunds",
  primary action "Export"
- A StatCard row: Total / Pending / Approved
- A table of requests: customer, amount, date, status badge,
  approve button per row

Data: add typed demo records to src/lib/data.ts.
Follow .cursor/rules/design-system.mdc: semantic tokens only,
existing components only. Run npx tsc --noEmit when done.

Save prompts like this in the repo so the whole team (and future you) starts from the same template.

5. Check the output in seconds

Rules reduce drift; they do not eliminate it. Two quick checks catch nearly everything:

  • Search for hardcoded colors in components: grep -rnE "#[0-9a-fA-F]{3,6}\b" src/components src/app. Anything outside your token file is a bug.
  • Toggle dark mode. A component that only looks right in one theme is using raw values somewhere.

When you find a violation, fix the rule that allowed it, not just the file. The next hundred generations get better instead of just this one.

The short version

  1. Semantic tokens in CSS, with the same names as your Figma variables.
  2. An always-on rules file for Cursor, imported by Claude Code through CLAUDE.md.
  3. A component inventory in the rules, so the model reuses instead of rebuilds.
  4. Structured prompts saved in the repo.
  5. A grep for hex values and a dark-mode toggle after every change.

GliaKit ships exactly this setup: the token file, .cursor/rules, AGENTS.md with a CLAUDE.mdimport, a prompt library, and a Figma file whose variables match the CSS by name. You can read every component’s API on the components page or see the rules in action in the docs.