How to Make Your AI-Generated Website Look Like You Built It
Inter, #3B82F6, three cards in a row: the five tokens that mark a site as AI-built. Here's how to rewrite them in an afternoon without touching the component logic.
You asked v0 to build your landing page. It came out fast, functional, and completely generic. Inter font. #3B82F6 primary. Three cards in a row. Centered hero with an eyebrow badge. You have seen this exact site a thousand times — because Cursor, Lovable, Bolt, and Framer AI all ship the same one.
This is not a knock on the tools. They produce exactly what they were trained on: the most common patterns on the web. The problem is that the most common patterns are indistinguishable from each other. Your product may be genuinely different. Your website is not. (For why this convergence happens at all, see why every AI-generated website looks the same.)
Here is the process to fix it.
The 5 layers AI always gets wrong
AI-generated sites fail on five specific dimensions. Fix all five and the site stops looking generated. Skip one and the tell survives — a perfect palette with Inter headings still reads as scaffolded.
Layer 1: Typography
Every AI tool defaults to Inter. Sometimes it drifts to system-ui, Roboto, or Geist (Vercel's house font, and increasingly its own fingerprint). All of these are fine fonts. They are also on millions of sites. Combine Inter with left-aligned body copy and two weights — 400 and 600 — and you have rebuilt the single most common typographic signature on the web.
The fix is a pairing: one display font for headings, one body font for text, and the two should not share a category. If your display is a serif (Playfair Display, Fraunces, Cormorant Garamond), pair it with a neutral sans (Karla, Work Sans). If your display is geometric or condensed (Archivo Black, Bebas Neue), give the body some personality (Raleway, Barlow).
Do not reach for: Inter, Roboto, Poppins, Open Sans, Montserrat, Lato.
/* Generic (the default) */
body { font-family: 'Inter', system-ui, sans-serif; }
/* Distinctive */
:root {
--f-display: 'Playfair Display', Georgia, serif;
--f-body: 'Karla', system-ui, sans-serif;
}
h1, h2, h3 { font-family: var(--f-display); }
body { font-family: var(--f-body); }This one change makes a site look designed rather than scaffolded. It costs nothing and takes ten minutes. (Why Inter is killing your brand goes deeper on the why.)
Layer 2: Color
AI tools default to one of three color bands:
- Blue-indigo (hue 210-240): #3B82F6, #6366F1 — by far the most common
- Purple-violet (hue 255-280): #8B5CF6, #7C3AED
- Teal-cyan (hue 180-200): #0EA5E9, #06B6D4
Clean colors, all of them. They are also instantly recognizable as defaults. People have seen them so often that the association — generated — fires before they can name it.
The fix is one decision: pick a hue outside those bands. Hue 0-180 and 290-360 are almost entirely free of AI defaults. A red-orange at hue 20, a yellow-green at hue 80, a deep magenta at hue 320 — any of them breaks the pattern on sight.
/* AI default */
--primary: #3B82F6; /* hue 220 — the most common AI color */
/* Distinctive */
--primary: hsl(347, 72%, 48%); /* deep rose — hue 347, outside AI band */
/* or */
--primary: hsl(22, 85%, 52%); /* burnt orange — hue 22 */
/* or */
--primary: hsl(156, 60%, 38%); /* forest green — hue 156 */Check the background too. Pure #ffffff and #000000 are defaults. A warm white — hsl(35, 20%, 96%) — or a tinted dark — hsl(220, 15%, 8%) instead of the ubiquitous zinc-950 — reads as a choice, not a fallback. (More on picking an accent that isn't Tailwind blue: how to pick an accent color.)
Layer 3: Layout and spacing
AI tools reach for two layouts:
- Three equal columns for features
- Centered single column for everything else
Equal-column grids signal template. Three identical cards specifically kill conversion because the eye reads "filler" before it reads any of the three. The fix is an asymmetric ratio. A 5fr/3fr split looks designed. A 7fr/4fr grid with content left and a code block right looks like a product company shipped it.
/* AI default */
.features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
/* Distinctive */
.features { display: grid; grid-template-columns: 5fr 3fr; gap: 3rem 4rem; }For spacing, AI tools use one gap value everywhere — usually gap-4 or gap-6 in Tailwind. Vary it deliberately instead: wide between sections, tight within them. The contrast between density and air is what the eye reads as rhythm.
Layer 4: Border radius
AI tools paste rounded-lg (0.5rem) onto everything — buttons, cards, inputs, avatars, code blocks. When every corner matches, the site looks assembled from a kit.
The fix is two independent radii: one for interactive elements, one for containers, and they should disagree. A 4px button with a 0px card looks editorial. An 8px button with a 2px card looks product-like. The mismatch is the signal that someone chose.
/* AI default */
--radius: 0.5rem; /* applied to everything */
/* Distinctive */
--r-btn: 4px; /* small and direct */
--r-card: 0px; /* sharp, editorial */
/* or */
--r-btn: 6px;
--r-card: 14px; /* soft containers, precise buttons */Layer 5: Animation
AI tools ship one animation: opacity 0→1 with translateY(20px→0), 300ms, ease-in-out. The "fade-up." It lands on every section, every card, every button on scroll, and the uniformity is the tell — a human would never animate a headline and a footer link the exact same way.
The fix is variation by component type. The hero headline clip-reveals left to right. The feature list slides in from the left axis with a stagger. The CTA scales up from 95%. Different motions for different jobs reads as authored.
/* AI default */
@keyframes fadeUp { from { opacity: 0; transform: translateY(20px); } }
.section { animation: fadeUp 300ms ease-in-out; }
/* Distinctive — vary the pattern per component type */
@keyframes clipReveal { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0% 0 0); } }
@keyframes slideFromLeft { from { opacity: 0; transform: translateX(-30px); } to { opacity: 1; transform: translateX(0); } }
@keyframes scaleUp { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
h1 { animation: clipReveal 0.7s cubic-bezier(0.16, 1, 0.3, 1); }
.feature-list { animation: slideFromLeft 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); }
.cta-section { animation: scaleUp 0.5s ease-out; }A worked diff: hero in 40 minutes
You do not need a redesign. You need to retarget tokens. Here is the before — a default Tailwind hero from any AI builder:
<section class="text-center py-24 bg-white">
<span class="rounded-lg bg-blue-100 text-blue-600 px-3 py-1">New</span>
<h1 class="font-sans text-5xl font-semibold">Build faster</h1>
<button class="rounded-lg bg-blue-500 text-white px-6 py-3">Get started</button>
</section>Five edits, no markup restructuring:
<section class="text-left py-32 bg-[hsl(35,20%,96%)]">
<span class="rounded-[2px] bg-[hsl(347,72%,48%)]/10 text-[hsl(347,72%,48%)] px-3 py-1">New</span>
<h1 class="font-[Cormorant_Garamond] text-6xl font-medium">Build faster</h1>
<button class="rounded-[4px] bg-[hsl(347,72%,48%)] text-white px-6 py-3">Get started</button>
</section>Same DOM, same component, same props. Centered → left-aligned, Inter → Cormorant, blue → rose, rounded-lg everywhere → 2px badge / 4px button, warm-white ground instead of pure white. The diff touches class strings only — and it no longer looks like the tool that generated it.
The fast path: scan first, fix what scores low
If a project already exists, scan it before editing. The scan tells you which of the five layers is worst, so you spend the afternoon where it counts:
npx sailop install
sailop scan ./srcThe output grades each dimension A to F. Fix the F scores first, then the D scores. Most AI-generated projects score worst on color (F) and typography (D or F); layout and animation usually land in the C range. (Sailop is a linter for design — same idea as ESLint, applied to the visual layer.)
What not to change
Plenty is fine to leave alone:
Component structure. The JSX, the hierarchy, the prop interfaces — all fine. You are changing design tokens, not architecture.
Accessibility. ARIA labels, semantic HTML, keyboard nav: if the AI got these right, keep them. They are correct.
Responsive breakpoints. AI tools usually handle mobile well. Leave the breakpoint logic; only retarget the visual values inside it.
Content and copy. Unless it is also generic ("Seamlessly streamline your workflow with our AI-powered platform" — rewrite that), the structure can stay. Fix the words, not the skeleton.
The result
A site that went through this:
- Display font: Cormorant Garamond (serif, editorial)
- Body font: Karla (neutral sans, readable)
- Primary: hsl(347, 72%, 48%) — deep rose
- Feature layout: 5fr 3fr grid
- Button radius: 4px, card radius: 0px
- Hero animation: clip-reveal
- Feature animation: x-slide with stagger
Put it next to a default AI output and they do not look like the same tool made them. That is the entire point.
Use Sailop to automate this
Sailop's transform command runs all five fixes at once. It derives values from your project seed, so every project lands on a different result — no shared signature across the sites you ship:
sailop transform ./src
# Rewrites: font imports, color variables, grid ratios, radius values, animation keyframes
# Does not touch: component logic, content, accessibility attributesscan tells you what is broken; transform fixes it. For anything already in production, scan first, read the report, then apply the fixes you trust by hand.
SHIP CODE THAT LOOKS INTENTIONAL
Scan your frontend for AI patterns. Generate a unique design system. Stop shipping the same blue gradient as everyone else.