
The Claude Code prompts that produce shippable UI name values and a check; the ones that fail name a mood. "Make it modern and clean" leaves every color, size, curve and state for Claude to fill with defaults. "Colors only from tokens.css, all six states, 240ms on transform only, then screenshot it at 375px" leaves nothing open, and Claude Code follows it.
Anthropic's best practices for Claude Code say the same thing in general terms: write a specific prompt, hand over the screenshot instead of describing it, give Claude a check it can run, and ask for the evidence. The ten prompts below apply that to interface work, in the order a build uses them: set up the design, build the parts, check the result.
Why most UI prompts come back generic#
A single component carries a dozen decisions: radius, border, padding, type size, the hover change, its duration and curve, the focus ring, the disabled look. A prompt that names none of them gets the category median for each, and the median is easy to recognize:
border-radius: 8pxon everything from the button to the modal.box-shadow: 0 1px 3px rgba(0,0,0,0.1), the framework default.transition: all 0.2s ease, which animates properties nobody meant to animate.- A
1pxgray border with no relation to the surface behind it.
All of that code works, and nobody chose any of it. The frontend model comparison shows the same list coming back from every current model, because the model is filling gaps rather than making choices.
There is a second failure that has nothing to do with values. Claude tends to read a request conservatively and build the smallest thing that satisfies it, according to Anthropic's own docs, which suggest saying be ambitious and then naming the scope. "A pricing card" gets a card. "A pricing card with monthly and yearly toggles, a highlighted plan, a disabled state for the current plan and keyboard focus through every control" gets the component you meant.
So a prompt that ships closes two gaps: the values Claude would guess, and the scope it would trim.
The anatomy of a prompt that ships#
Every prompt below is built from the same seven parts. Not every prompt needs all seven, but each part you leave out is a decision you hand back to the model.
| Part | What it closes | Example line |
|---|---|---|
| Scope | which file, which component, how far | "Edit only src/components/PricingCard.tsx" |
| Reference | what it should match | @src/components/Card.tsx, or a pasted screenshot |
| Values | color, type, spacing, radius | "--color-accent only, padding 20px 32px from the ramp" |
| States | what the element does | rest, hover, focus-visible, active, disabled, loading |
| Motion | how it moves and what stays still | "transform only, 240ms, cubic-bezier(0.32, 0.72, 0, 1)" |
| Limits | what not to add | "no new dependencies, no new hex values" |
| Check | how Claude knows it is done | "screenshot at 375 and 1440, tab through every state" |
The check is the part most prompts leave out, and it is the one that changes how Claude works. With a check, Claude makes the change, runs it, reads the result and fixes what failed before it reports back. Without one, it stops when the work looks done, and you become the test suite.
A whole page is the same anatomy at a larger scale. These three were built from Thanor art directions that fill every row for an entire site, down to the media:
A cream alpaca mascot follows the cursor with a slow side-eye on bright blue, with stat pills: a SaaS hero with a character.
Open the prompt →A giant black BRISK over a looping pink clay ribbon on lilac, with stickers: a fintech landing in heavy type over video.
Open the prompt →An AI agent called Tuki: a baby emperor penguin in dithered monochrome beside a terminal-style headline.
Open the prompt →Prompts that set up the design#
Run these once per project. They turn a direction into files that every later prompt can point at.
1. Interview me into a design spec#
Anthropic's docs suggest asking Claude to interview you until it could write the spec. For design work, list the questions it must cover:
I want a landing page for [product]. Before any code, interview me until you
could write the design spec: audience, the one action the page asks for, palette
as hex with a role for each value, typefaces, type scale, spacing ramp, motion
curves and durations, section order with the job of each section, and the media
I already have. Ask in short multiple-choice rounds. Then write design/SPEC.md.The interview turns decisions you have not made yet into questions with options, so the choices end up yours. The file it writes becomes the one source every later prompt points at, and the docs suggest starting a fresh session from it so the build begins with a clean context.
2. Turn the spec into tokens#
Read @design/SPEC.md and write src/styles/tokens.css as CSS custom properties:
--color-* for each hex with its role, --font-display and --font-text, a type
scale from 17px at ratio 1.25 as --step-0 to --step-6, the spacing ramp
4 8 12 20 32 52 84, --radius-control 2px, --radius-card 14px,
--ease-out cubic-bezier(0.22, 1, 0.36, 1), --ease-ui cubic-bezier(0.32, 0.72, 0, 1),
--dur-ui 240ms, --dur-reveal 640ms. Define nothing that is not in the spec.Every token is named and extras are forbidden, so Claude transcribes the values and invents none. Custom properties are also the easiest thing to audit later: any value that is not a var() is a value nobody chose.
3. Make the rules load every time#
Create .claude/rules/ui.md, scoped with a paths field to src/components/** and
src/styles/**. Rules: colors, sizes and durations come only from tokens.css;
every transition lists its properties and never uses "all"; every interactive
element has rest, hover, focus-visible, active and disabled states; every
animation has a static end state under prefers-reduced-motion.Path-scoped rules load only when Claude works on matching files (memory docs), so the UI rules stay out of the way of backend work. Each rule is also written as something Claude can check in its own diff: a transition either lists its properties or it does not.
Prompts that build components and sections#
One component or one section per prompt. Several at once and the later ones get less care.
4. A component with every state#
Build src/components/Button.tsx in the style of @src/components/Card.tsx.
Variants: primary, secondary, ghost. States: rest, hover, focus-visible, active,
disabled, loading (a spinner replaces the label and the width stays fixed).
Hover: translateY(-1px), background 8% lighter, var(--dur-ui) var(--ease-ui),
transform and background-color only. Focus: 2px solid var(--color-accent),
offset 3px. No new dependencies. Show me every state in one screenshot.Six named states are six things Claude builds; "a polished button" gets one state and a hover. The fixed width while loading stops the layout from jumping when the label changes, and one screenshot of every state gives you a single image to review.
5. A hero with one motion sequence#
Build the hero from @design/SPEC.md, section 1. Headline at var(--step-6), at
most three lines at 375px wide. On load, one sequence: headline lines rise 24px
and fade in, var(--dur-reveal) var(--ease-out), stagger 80ms; then the media
fades in over 400ms. Nothing else in the hero animates. Under
prefers-reduced-motion, render the end state with no animation.The prompt names the one moment that moves and says that nothing else does, which is the restraint the frontend-design skill asks for, written as a constraint. The three-line limit at 375px is something Claude can verify in a screenshot. The motion numbers follow the motion design prompt, which has the full table of distances, durations and curves.
6. An element that follows the pointer#
Make the mascot's eyes follow the pointer. Map pointer position to a rotation of
at most 12deg, eased toward the target each frame with a lerp factor of 0.12,
and pause the loop when the hero is off screen (IntersectionObserver). On touch
devices, return the eyes to center after 1.5s. Under prefers-reduced-motion the
eyes stay fixed, looking at the headline.Each number is a decision a default gets wrong. An unclamped rotation looks broken at the edge of the screen, an angle assigned directly, with no easing, looks jittery, and a loop that never pauses keeps running on every page view. Touch and reduced motion each get a deliberate behavior.
Pointer-driven characters are one of the most direct ways to make a page feel made rather than assembled, and they are small enough to build in one prompt:
A ginger kitten on teal chases the red laser dot you steer: a character driven by the pointer, with a running marquee.
Open the prompt →A studio footer where a knitted creature's pupils follow your cursor, with three columns of dark type set on the picture.
Open the prompt →7. A footer that ends the page#
Build the footer as the page's closing scene. Full-bleed image from
/media/footer.jpg, three columns of links set directly on it in var(--color-ink)
at var(--step--1), the brand name at var(--step-5) along the bottom edge, and
24px of clear space around the columns at 375px. No divider lines, no social
icon row unless the spec lists accounts.A footer is where generated pages fall back to four gray columns and a row of icons. Naming the image, the type steps and the clear space makes it a scene, and the last line stops Claude from inventing social accounts you do not have. More examples are in website footer design.
Prompts that check the work#
Give Claude a check it can run, and it can close the loop itself. These three cover how the page looks, how it performs and whether it drifted.
8. Screenshot review at three widths#
Open the page in the browser. Screenshot every section at 375, 768 and 1440 px.
Report: any horizontal scroll, any headline over three lines, any text under
14px on mobile, any element that overlaps another, any image without explicit
dimensions. Fix each issue, re-screenshot, and show me before and after.Each item is pass or fail, which is what lets Claude fix and re-check without you, and the before-and-after screenshots are the evidence the docs tell you to ask for. In the desktop app this runs in the built-in Browser pane. In the terminal, start Claude Code with claude --chrome, or add the Playwright MCP server.
9. Accessibility and speed#
Using the Chrome DevTools MCP, run lighthouse_audit and a performance trace on
the home page. Fix text below 4.5:1 contrast, controls without a visible focus
state, and anything that pushes Largest Contentful Paint past 2.5s or Cumulative
Layout Shift past 0.1. Report the numbers before and after.The thresholds are Google's "good" targets for Core Web Vitals, and asking for numbers before and after makes the fix verifiable in a way "make it faster" never is. Setup for that server, and for the others worth adding, is in the best MCP servers for web design.
10. A drift audit#
List every hex color, px size and duration in src/ that is not defined in
src/styles/tokens.css, with file and line. Replace each with the nearest token,
or tell me why it needs a new one. Do not add tokens without asking.Run it after every few sessions. Drift is quiet: one 18px gap here and one #1E1E1E there, each defensible, none of them yours. The last sentence of the prompt matters too, because without it the easiest fix is a new token for every stray value, which hides the drift and removes none of it.
When the prompt has to be a whole art direction#
The ten prompts above direct a part of the page. A whole site needs the direction itself: the palette in hex, the typefaces and scale, spacing, every curve and duration, the section order, every interaction, and the media the page uses. Writing that is the part that takes days, and it is what turns prompts 4 to 7 from guesses into executions.
That is what each Thanor design comes with: a long prompt that is a full art direction written as values (what it contains, block by block), plus hosted films, cut-outs or stills that the built page uses. There are two ways to get one into Claude Code:
- Paste it. Open a design, copy its prompt, and give it to prompt 1 in place of the interview, or save it as
design/SPEC.md. - Fetch it. Connect the Thanor MCP with
claude mcp add --transport http thanor https://thanor.ai/api/mcp, approve it in/mcp, and ask Claude to search the library and pull a direction withget_prompt(setup).
The frontend-design skill pairs well with either route: its text tells Claude to follow a brief that pins down the direction, and it adds a plan step and a quality floor on top (what the skill does). For the full build sequence around these prompts, see how to build a website with Claude Code, and for a 3D hero, the 3D website guide has the scene values.
Mistakes that waste a prompt#
Most wasted prompts fail in one of a handful of ways, and each has a one-line fix.
- Asking for "polished". It is an adjective. Name the states, the curve and the duration.
- Several components in one prompt. The first gets care, the last gets the median. One per prompt.
- No reference.
@a finished component or paste a screenshot, and Claude matches it instead of inventing a sibling. - No check. Without a screenshot or a test, "looks done" is all Claude has to go on, and the docs say so.
- Correcting with moods. "Make it pop" sends Claude guessing again. "Accent to
#FF4D8D, headline tovar(--step-6)" does not. - Values only in the conversation. Anything not in
tokens.css,CLAUDE.mdor a rule file is gone by the next session. - A new direction in an old session. Earlier decisions still sit in the context and leak into the new one. Run
/clearbetween unrelated tasks, or start a fresh session from the spec file.
Start from a direction instead of a blank#
Open Vesperion and copy its prompt; it is free with an account. Save it as design/SPEC.md, skip the interview, and run prompts 2 to 10 against it. You will see how much shorter every later prompt gets when the direction already exists, because each one only has to point at values that are written down.
The rest of the library works the same way, and the paid plans on pricing include the Thanor MCP, so Claude Code can fetch a direction without the clipboard.
Questions this raises
What is a good Claude Code prompt for UI?
One that names the file, the reference to match, the values to use, the states to build, how it moves and what proves it is done. For example: build Button.tsx in the style of Card.tsx, colors only from tokens.css, all six states, transform only at 240ms, then screenshot it at 375 and 1440 pixels wide. Adjectives such as modern or clean close none of those decisions.
How do I make Claude Code follow my design system?
Write the system as a token file of CSS custom properties, import the specification from CLAUDE.md so it loads every session, and add a path-scoped rule in .claude/rules/ that applies to your component folders. Then run a drift audit that lists every color, size or duration not defined in the token file, and replace each one.
Should I paste screenshots into Claude Code?
Yes, when you have a visual target. Anthropic's best practices say to hand over the screenshot of the design instead of describing it, and Claude Code accepts images by drag and drop, by pasting with Ctrl+V, or by file path. Pair the screenshot with the values it implies, because a picture does not carry an exact hex or duration.
Why does Claude Code build less than I asked for?
Anthropic's best practices note that Claude tends to read a request conservatively and build the smallest thing that satisfies it. Say what scope you want: the docs suggest the phrase be ambitious, followed by the specifics, such as empty and error states, keyboard navigation and the full save flow.
Where should I keep UI prompts I reuse?
Save each one as a skill: a folder in .claude/skills/ with a SKILL.md file, which you run by typing its name as a slash command. Older files in .claude/commands/ still work, but skills add supporting files and can load automatically. Keep the values themselves in the token file, so every saved prompt points at one source.
Part of
Build it with AI
Three dimensional scenes, scroll driven motion and animated pages, built by handing a model a specification instead of an adjective. What to write, and what comes back.
