PROJECT 4
×00

Stop Shipping AI-Looking Websites: A Field Guide to Directing Claude Code

Design · Working with AI

Every AI-generated site has the same tell. The fix isn't a better tool. It's directing the model with a real brief, a design plan, and your boldness spent in exactly one place.

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:

  1. 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.
  2. 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.
  3. 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:

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.

A generic AI-styled hero: cream background, large serif
  "Transform your workflow" headline, terracotta "Get Started" button, a soft
  gradient blob in the corner, and a row of fake company logos under "Trusted by teams
  worldwide."
The default: cream, serif, terracotta, a gradient blob, and borrowed social proof.
<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."

A subject-derived hero for a film-production tool: warm
  paper background, a heavy condensed uppercase headline reading "Your whole shoot day on one
  sheet" with "one sheet" in amber, and a tilted call-sheet card on the right showing
  crew call, shooting call, location, weather, and scene numbers in monospace, topped by a
  clapperboard stripe.
Directed: the hero is a call sheet. One bold idea, everything else disciplined.
<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&nbsp;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:

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:

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.