I've shipped a lot of front-end with Claude Code over the last year, and I've also reviewed a lot of front-end that other people shipped with it. There's a tell. You learn to spot it from across the room: the cream background, the high-contrast serif headline, the three feature cards with thin-line icons, the "Transform your workflow" hero, the gradient blob bleeding off the top-right corner. It's competent. It's responsive. It's also instantly recognizable as something nobody actually designed.
The good news is that this is a directing problem, not a tooling problem. Claude Code is fully capable of producing distinctive work. It defaults to generic output for the same reason a session musician defaults to safe choices when you don't tell them what song you're making: under-specification gets you the mean of everything plausible. Your job is to remove that ambiguity. Here's how I do it.
First, learn to recognize the tells
You can't prevent what you can't see. Right now, AI-generated web design clusters around three looks, and once you've named them you'll see them everywhere:
- The warm editorial. Cream background (somewhere around
#F4F1EA), a big high-contrast serif display face, a single terracotta accent. Tasteful, and completely generic because it shows up regardless of what the site is selling. - The dark acid. Near-black background, one bright acid-green or vermilion accent, lots of glow. Looks like every developer-tool landing page from the last two years.
- The broadsheet. Hairline rules everywhere, zero border-radius, dense newspaper-style columns, a tiny monospace eyebrow label over everything.
None of these is bad. The problem is that they appear as defaults rather than choices: the model reaches for them no matter the brief. If you ask for a yoga studio, a B2B compliance tool, and a hot-sauce brand, and you get back three variations on the same cream-and-serif treatment, that's the tell.
The visual look is only half of it. The copy gives it away just as fast:
- Verbs like Transform, Elevate, Unlock, Supercharge, Empower.
- Seamlessly and effortlessly, usually within the first two sentences.
- The feature triplet: three cards, three lucide icons, three two-word headings.
- Social proof with no proof: "Trusted by teams worldwide," "Join thousands of users."
- A hero that describes a category instead of a product: "The all-in-one platform for modern teams."
And the structural clichés: the 01 / 02 / 03 numbered steps used on content that
isn't actually a sequence, the testimonial carousel nobody asked for, the FAQ accordion padding out
the page, the pricing table with the middle tier scaled up 5%.
If you can name these in a code review, you can stop them before they ship.
The root cause: you gave it nothing to react to
"Build me a landing page for my app" is a request for the average landing page. The model has no subject to ground decisions in, so it produces decisions that work for any subject, which is the definition of generic.
Everything below is, fundamentally, a way of giving Claude Code something specific to react to.
A worked example: same product, two heroes
Let me make this concrete with the brief from earlier: a project tool for film production crews. Here's what you get from the generic path, and what you get when you direct it.
Before: the default
This is roughly what "make a modern landing page for my project tool" produces. Cream background, serif display, terracotta accent, a gradient blob, a category-not-product headline, and "Trusted by teams worldwide" over invented logos. It's clean. It's also indistinguishable from a thousand other pages, and nothing in it says film.
<section class="hero">
<div class="blob"></div> <!-- the obligatory gradient blob -->
<p class="eyebrow">The future of productivity</p>
<h1>Transform your workflow</h1>
<p class="sub">The all-in-one platform for modern teams to plan,
track, and ship faster — effortlessly.</p>
<button class="btn-primary">Get Started</button>
<button class="btn-ghost">Learn more</button>
<p class="trusted">Trusted by teams worldwide</p>
<div class="logos">ACME · GLOBEX · INITECH · HOOLI · UMBRELLA</div>
</section>
body { font-family: "Inter", sans-serif; background:#F4F1EA; color:#2b2b2b; }
h1 { font-family:"Lora",serif; font-size:64px; text-align:center; }
.blob { position:absolute; top:-160px; right:-120px; width:520px; height:520px;
border-radius:50%;
background:radial-gradient(circle at 30% 30%,#E7B7A6,#C56A4E 60%,transparent 72%);
filter:blur(8px); }
.btn-primary { background:#C56A4E; color:#fff; border-radius:999px; padding:15px 30px; }
Count the tells: centered serif headline, the verb Transform, effortlessly in the subhead, the gradient blob, the radius-999 pill button, the fake-logo social proof. Every one of those is a default, not a decision.
After: directed by the subject
Same product, but now the brief is doing the work, and the design is derived from the artifact the audience already lives in: the call sheet. The signature element is a stylized call sheet (clapperboard stripe, monospace tabular production data, a sunset stamp, scene tags). Everything else stays quiet so that one element carries the page. The type is a heavy condensed sans for display and a monospace for data. Not a serif in sight. The copy speaks the audience's language, and the CTA names something specific instead of "Get Started."
<section class="hero">
<div class="left">
<p class="eyebrow"><b>Call sheet</b> Day 14 of 31 · Ext. Day</p>
<h1>Your whole shoot day on <span class="amber">one sheet.</span></h1>
<p class="lede">Call sheets, shooting schedules, and location logistics —
built by people who've stood on a set at 5 a.m.
No more group-text chaos.</p>
<button class="btn-primary">See a sample call sheet</button>
<button class="btn-text">Watch the 2-min walkthrough</button>
<p class="reassure mono">Imports your spreadsheet. Texts the crew.
Tracks the company move.</p>
</div>
<!-- the signature: the hero IS a call sheet -->
<aside class="sheet">
<div class="clap"><span></span><span></span><span></span>…</div>
<header class="sheet-h">
<div><b class="title">THE LAST EXIT</b>
<span class="sub mono">Prod #2208 · Sun 28 Jun</span></div>
<span class="stamp">SUNSET 20:41</span>
</header>
<dl class="rows mono">
<div class="row"><dt>Crew call</dt><dd>06:00</dd></div>
<div class="row"><dt>Shooting call</dt><dd class="amberbox">07:30</dd></div>
<div class="row"><dt>Location</dt><dd>Pier 7 — Lot B</dd></div>
<div class="row"><dt>Weather</dt><dd>14° · clear · wind 9kt</dd></div>
</dl>
<div class="scenes mono">
<span class="scene">SC 24A</span><span class="scene">SC 31</span>…
</div>
</aside>
</section>
body { font-family:"Liberation Sans",sans-serif; background:#E9E3D4; color:#16130D; }
h1 { font-family:"Archivo","Arial Narrow",sans-serif; font-weight:800;
font-size:74px; line-height:.94; text-transform:uppercase; }
.amber { color:#E0922B; }
.mono { font-family:"DejaVu Sans Mono",monospace; } /* data reads as data */
.sheet { background:#F4EFE2; border:2px solid #16130D;
box-shadow:10px 10px 0 #16130D; transform:rotate(-1.2deg); } /* one bold move */
.clap span:nth-child(odd){ background:#16130D; } /* clapperboard stripe */
.btn-primary { background:#16130D; color:#E9E3D4; } /* square, not a pill */
Nothing here would survive being pasted onto a different brief, and that's the point. The square
buttons, the grease-pencil shadow, the monospace logistics, the SUNSET 20:41 stamp. They
only make sense for this product. That's the difference between a page that was
generated and a page that was designed.
A caveat in the spirit of restraint: the "after" leans hard on one idea. That works because everything around the call sheet is disciplined. If you also tilted the headline, added a second accent, and animated the scene tags, you'd be back to noise. Spend the boldness once.
1. Write a real brief before you write a prompt
Before I open Claude Code, I pin down three things and I put them in the prompt verbatim:
- The concrete subject. Not "a SaaS app," but "a tool that lets indie game studios track playtester feedback."
- The audience. Not "users," but "solo and small-studio developers who live in Discord and distrust marketing."
- The page's single job. What is the one thing this page must accomplish? Get a demo signup? Communicate trust to enterprise buyers? Sell one product?
That last one is the most underused. A page with one job can make sharp choices. A page trying to do everything defaults to the safe everything-template.
Weak prompt: "Make a modern landing page for my project management tool."
Strong prompt: "Landing page for a project tool built specifically for film production crews: call sheets, shooting schedules, location logistics. Audience is line producers and ADs who currently run everything off spreadsheets and group texts and are skeptical of 'project software.' The page has one job: convince them this was built by people who understand a set, not by Silicon Valley. Lean into the vernacular of production: call times, scene numbers, the language of the slate."
The second prompt can't produce a generic page, because a generic page wouldn't satisfy it.
2. Make it plan the design before it writes any code
This is the single highest-leverage habit. Don't let Claude Code jump straight to JSX. Ask for a design plan first, and be specific about what the plan must contain:
"Before writing any code, give me a design plan: a palette of 4 to 6 named hex values, a type pairing (a characterful display face used with restraint, plus a body face, not Inter), a layout concept with a rough ASCII wireframe, and one signature element this page will be remembered by. Justify each choice against the brief. Don't write code yet."
A few things this buys you. You get to veto the cream-and-serif default at the planning stage, which costs seconds, instead of after a full build, which costs a rebuild. You force the model to articulate why each choice fits this specific subject. And you get a "signature," the one memorable thing, which is exactly what generic sites lack.
When the plan comes back, apply one test: would I get roughly this same plan for a completely different brief? If yes, it's a default wearing a costume. Push back: "The palette and serif headline would fit any premium brand. Give me something that could only belong to this one."
3. Kill the defaults by name
The model has strong gravitational pulls toward certain choices. Name them and forbid them, or it'll drift back. I keep a running list in my prompts:
- "Don't use Inter, and don't use a generic system font stack for display. Pick a display face with a point of view."
- "No gradient mesh blobs. No glassmorphism. No
01/02/03step numbers unless the content is genuinely sequential." - "Don't reach for cream-and-serif, dark-mode-with-one-acid-accent, or the hairline-broadsheet look. I want something derived from the subject, not a template."
- "Border-radius, shadows, and spacing should be deliberate values from a scale, not the framework defaults."
This feels heavy-handed. It works. You're not insulting the model; you're removing the easy paths so it has to find the interesting one.
4. Give it real content, then fix the copy yourself
Lorem ipsum and placeholder copy are where genericness hides. If you let Claude Code invent the words, you'll get "Transform your workflow" and three feature cards. Feed it your actual value proposition, your actual product names, your actual customer language.
Then review the copy as ruthlessly as the design. Good interface copy names things by what the user controls, uses active voice ("Save changes," not "Submit"), and is specific instead of clever. A button that says "Publish" should produce a toast that says "Published," not "Success!" If the empty states and error messages read like a person apologizing, rewrite them in the product's voice. Copy is design material. It can make a page feel as templated as any layout choice.
5. Force an explicit self-critique pass
After the first build, before you touch anything yourself, make the model audit its own work against the very tells we listed:
"Critique this design as if you're a design lead who hates generic AI output. Where does it look templated? Which choices would appear regardless of the brief? What's the one element a person would actually remember? Then revise, and tell me what you changed and why."
Claude Code is genuinely good at this when you point it at the right target. The first pass is the model playing it safe; the critique pass is where it earns its keep. I often run this twice. Coco Chanel's rule applies to interfaces too: before you ship, look at it and take one thing off. Over-decoration (too many animations, too many accents, too much going on) is itself a strong AI tell.
6. Iterate visually, not just from the diff
Reading the code tells you what's there; it doesn't tell you what it looks like. If your setup lets the model take and view screenshots, use it. A screenshot is worth a thousand tokens of guessing. "Here's how it rendered; the hero feels cramped and the accent color is doing nothing. Fix the rhythm" is a far better instruction than anything you can give blind. If you can't automate screenshots, paste them in yourself. The visual feedback loop is where good design actually happens.
7. Lock your conventions in a project file
For anything bigger than a one-off, put your design system in a CLAUDE.md (or
equivalent) at the repo root: the palette, the type scale, the spacing tokens, the component
patterns, and a short "things we never do" list. This stops the slow drift back toward defaults
across a long session, and it means every new component inherits your point of view instead of the
model's. Treat it like a styleguide a new hire would read on day one.
8. Spend your boldness in exactly one place
The instinct, once you've freed the model from defaults, is to let it be bold everywhere. Don't. The best work picks one signature move (an unusual hero, a distinctive type treatment, an orchestrated load animation) and keeps everything around it quiet and disciplined. A page where everything shouts reads as chaotic; a page where nothing does reads as generic. One memorable element, surrounded by restraint, is the whole game. Tell Claude Code this explicitly, because left alone it tends to either play it safe or decorate everything.
Things to watch for
Drift over long sessions. The further you get from your original brief, the more the model relaxes back toward defaults. New components added late in a session are the most likely to come back generic. Re-anchor periodically, or lean on that project file.
CSS that cancels itself out. When the model generates a lot of CSS, watch for
selector-specificity collisions, a type-based selector like .section fighting an
element-level one like .cta, especially around section padding and margins. The page
looks subtly broken and the cause isn't obvious. Ask for the spacing system to live in as few places
as possible.
The quality floor getting skipped for the sake of flair. Distinctive doesn't mean inaccessible. Hold the line on responsive down to mobile, visible keyboard focus, sufficient contrast, and reduced-motion support. A bold design that fails on a phone or for a keyboard user isn't bold, it's broken. Put these in the brief so they're non-negotiable.
Animation as a tell. Scattered hover effects and entrance animations on every element scream "generated." Motion should serve one purpose (an orchestrated load sequence, a single meaningful scroll reveal) or be absent. More animation is not more design.
The "uniqueness" that's actually just a different default. Sometimes you reject the cream-and-serif look and the model hands you the dark-acid look instead. That's lateral movement, not progress. Keep pushing until the direction is derived from the subject, not swapped for another template.
The mindset that ties it together
Every technique here is the same move repeated: replace ambiguity with specificity, and make the model commit to choices it can justify against this brief rather than any brief. Generic output isn't Claude Code failing. It's Claude Code correctly answering an under-specified question. Give it a real subject, a point of view to react to, a chance to plan, and a reason to critique itself, and it'll produce work that looks like a decision was made. Because one was. You made it.
That's the actual job, by the way. The model can generate a thousand variations faster than you can blink. Knowing which one is worth shipping is still your call.