Rebuilding a Generated Hero Section, Decision by Decision (2026)
One slop hero, rebuilt one change at a time. Full before-and-after code, every decision named, every diff copy-pasteable. No theory — just the eleven edits that move a hero off the assembly line.
Here is a hero section. A real one, the kind v0 hands you in four seconds when you type "landing page for a SaaS." I've seen this exact component, give or take a className, on maybe two hundred sites this year.
export default function Hero() {
return (
<section className="flex min-h-screen flex-col items-center justify-center px-4 text-center">
<div className="mb-6 inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-zinc-50 px-4 py-1.5 text-sm text-zinc-600">
<span>✨</span>
<span>Trusted by 10,000+ teams worldwide</span>
</div>
<h1 className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-5xl font-bold tracking-tight text-transparent sm:text-7xl">
Supercharge your workflow
</h1>
<p className="mt-6 max-w-2xl text-lg text-zinc-600">
The all-in-one platform to streamline your work, boost productivity,
and unlock your team's full potential.
</p>
<div className="mt-8 flex gap-4">
<button className="rounded-lg bg-blue-600 px-6 py-3 font-medium text-white transition hover:bg-blue-700">
Get Started
</button>
<button className="rounded-lg border border-zinc-300 px-6 py-3 font-medium text-zinc-700 transition hover:bg-zinc-50">
Learn More
</button>
</div>
<div className="mt-12 flex items-center gap-6 text-sm text-zinc-500">
<span>🚀 No credit card required</span>
<span>⭐ 4.9/5 rating</span>
<span>🔒 Enterprise security</span>
</div>
</section>
);
}Nothing here is broken. It compiles, it's responsive, Lighthouse won't complain. That's exactly the problem — it's competent and anonymous, the visual equivalent of a stock photo. Every signal in it is one of the 73 patterns that mark a page as machine-built: the centered stack, the blue-to-purple text gradient, the verb-first headline, the emoji trust row.
I'm going to rebuild it. Not redesign — rebuild, one decision at a time, each one a single named change with the diff that does it. By the end you'll have a hero that says something. Here's the order.
Kill the gradient headline
The from-blue-600 to-purple-600 clip-text gradient is the single loudest tell on the page. It's not a brand color, it's the absence of one — the default every generator reaches for because it looks like a decision without being one. I've written a whole autopsy of why this exact gradient is an AI signature, so I'll keep it short: solid ink, real weight.
- <h1 className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-5xl font-bold tracking-tight text-transparent sm:text-7xl">
- Supercharge your workflow
+ <h1 className="text-5xl font-semibold tracking-tight text-zinc-900 sm:text-7xl">
+ Supercharge your workflow
</h1>Replace the verb with the outcome
"Supercharge your workflow" is a verb with no object — it could sell a CRM, a coffee maker, or a CRM for coffee makers. Headlines that survive say what the reader gets, with a number or a noun they can picture. Drop the imperative, name the result.
- <h1 className="text-5xl font-semibold tracking-tight text-zinc-900 sm:text-7xl">
- Supercharge your workflow
+ <h1 className="text-5xl font-semibold tracking-tight text-zinc-900 sm:text-7xl">
+ Close the books in a day,<br />not the last week of the month.
</h1>If you can't fill in a concrete outcome here, the problem isn't the copy — it's that you don't yet know what the product does for someone. Fix that before you fix the markup.
Break the center axis
items-center justify-center text-center is the lazy man's layout: it works for anything, commits to nothing, and reads as a placeholder forever. A left-aligned headline with a right-hand visual gives the eye somewhere to travel and gives you room for a product shot. Split the section into a grid.
- <section className="flex min-h-screen flex-col items-center justify-center px-4 text-center">
+ <section className="mx-auto grid min-h-screen max-w-6xl grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">
+ <div className="flex flex-col items-start text-left">
+ {/* badge, headline, subhead, buttons go here */}
+ </div>
+ <div className="relative hidden lg:block">
+ {/* product screenshot / illustration */}
+ </div>
+ </section>Everything that follows lives inside that first The Note what changed beyond the emoji: the copy got specific. "Enterprise security" became "SOC 2 Type II." "No credit card required" became "Free for the first close" — a sentence that only this product could write. Two equal-weight buttons mean you haven't decided what you want the visitor to do. "Get Started" and "Learn More" are both empty — one's a non-promise, the other's a shrug. Make the primary action specific and demote the secondary to a text link. "Streamline your work, boost productivity, and unlock your team's full potential" is three banned verbs in one breath. It's the tricolon every model writes when it has nothing to say. Replace it with one sentence that names the mechanism. The right grid column is currently a comment. Empty hero real estate is a confession that there's nothing to show. Put the actual UI in it — a real screenshot beats any abstract gradient blob, and it answers "what is this" before the reader scrolls. Pure white with a centered stack is the canvas a generator hands back untouched. One subtle, off-axis tone — not a (Close the extra wrapper before Rip out the emoji trust badges
✨ 🚀 ⭐ 🔒 row is the fastest 30-second tell there is — emoji standing in for proof you don't have. Real trust is a logo wall, a named number, or a customer quote. If you have none of those yet, an honest single line beats four fake ones.- <div className="mt-6 inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-zinc-50 px-4 py-1.5 text-sm text-zinc-600">
- <span>✨</span>
- <span>Trusted by 10,000+ teams worldwide</span>
- </div>
+ <p className="mb-6 text-sm font-medium uppercase tracking-wider text-zinc-500">
+ Used by finance teams at Ramp, Mercury, and Brex
+ </p>- <div className="mt-12 flex items-center gap-6 text-sm text-zinc-500">
- <span>🚀 No credit card required</span>
- <span>⭐ 4.9/5 rating</span>
- <span>🔒 Enterprise security</span>
- </div>
+ <p className="mt-10 text-sm text-zinc-500">
+ Free for the first close. No card. SOC 2 Type II.
+ </p>Pick an accent that isn't blue-600
bg-blue-600 is the most-pressed button color on the internet. The button is the one element guaranteed to be looked at, so it's the worst place to default. Pick a hue that isn't on Tailwind's factory shelf — I lay out the whole method for choosing an accent that isn't Tailwind blue, but the one-line version: go warm or go deep, and define it once.// tailwind.config.ts
theme: {
extend: {
colors: {
+ ink: '#1a1a1a',
+ accent: '#c2410c', // burnt orange — warm, unusual, readable on white
},
},
},Rebuild the buttons with one real CTA
- <div className="mt-8 flex gap-4">
- <button className="rounded-lg bg-blue-600 px-6 py-3 font-medium text-white transition hover:bg-blue-700">
- Get Started
- </button>
- <button className="rounded-lg border border-zinc-300 px-6 py-3 font-medium text-zinc-700 transition hover:bg-zinc-50">
- Learn More
- </button>
- </div>
+ <div className="mt-8 flex items-center gap-6">
+ <a
+ href="/signup"
+ className="rounded-md bg-accent px-6 py-3 font-medium text-white transition-colors hover:bg-accent/90"
+ >
+ Run your first close free
+ </a>
+ <a href="/demo" className="text-sm font-medium text-ink underline-offset-4 hover:underline">
+ Watch the 2-min demo →
+ </a>
+ </div>Drop the marketing verb-soup in the subhead
- <p className="mt-6 max-w-2xl text-lg text-zinc-600">
- The all-in-one platform to streamline your work, boost productivity,
- and unlock your team's full potential.
- </p>
+ <p className="mt-6 max-w-md text-lg leading-relaxed text-zinc-600">
+ Reconciliations run themselves overnight. You review exceptions in the
+ morning, sign off, and the month is closed before lunch.
+ </p>max-w-2xl also became max-w-md. A 42rem line of body copy floating under a hero is a paragraph; a 28rem line reads like a sentence someone meant.Set type with measured weight, not just bold
font-bold everywhere is a generator habit — it has one volume knob and turns it to max. A real hierarchy uses font-semibold for the headline and lets weight, size, and color do the separating. I already softened the headline to font-semibold in step one; here's the deliberate choice to *not* bold the subhead and to give the eyebrow its own treatment. This is the same instinct behind escaping the Inter-and-bold default that flattens every brand — load a face with actual personality and let it breathe.// e.g. in your layout, swap the default
- import { GeistSans } from 'geist/font/sans';
+ import localFont from 'next/font/local';
+ // Self-host something with character — a grotesque or a serif display for the H1.
+ const display = localFont({ src: './Söhne-Halbfett.woff2', variable: '--font-display' });Add a product shot instead of empty space
<div className="relative hidden lg:block">
+ <img
+ src="/close-dashboard.png"
+ alt="Month-end close dashboard showing 3 open exceptions"
+ className="rounded-xl border border-zinc-200 shadow-2xl"
+ width={720}
+ height={480}
+ />
</div>Give the section a real background
from-blue-50 wash — grounds the hero and separates it from the section below. Warm paper, not cool default.- <section className="mx-auto grid min-h-screen max-w-6xl grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">
+ <section className="bg-[#faf8f5]">
+ <div className="mx-auto grid min-h-screen max-w-6xl grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">.)
Loosen the rhythm so it isn't a tower
The default stack spaces everything with one rhythm — mt-6, mt-8, mt-12 — a metronome. Vary the gaps so the badge hugs the headline and the buttons get air. Small, but it's the difference between typeset and dumped.
- <p className="mb-6 text-sm font-medium uppercase tracking-wider text-zinc-500">
+ <p className="mb-4 text-sm font-medium uppercase tracking-wider text-accent">The eyebrow also took the accent color — now the burnt orange appears twice (eyebrow and button), which reads as a system instead of an accident.
The full AFTER
export default function Hero() {
return (
<section className="bg-[#faf8f5]">
<div className="mx-auto grid min-h-screen max-w-6xl grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">
<div className="flex flex-col items-start text-left">
<p className="mb-4 text-sm font-medium uppercase tracking-wider text-accent">
Used by finance teams at Ramp, Mercury, and Brex
</p>
<h1 className="font-display text-5xl font-semibold leading-[1.05] tracking-tight text-ink sm:text-7xl">
Close the books in a day,
<br />
not the last week of the month.
</h1>
<p className="mt-6 max-w-md text-lg leading-relaxed text-zinc-600">
Reconciliations run themselves overnight. You review exceptions in
the morning, sign off, and the month is closed before lunch.
</p>
<div className="mt-8 flex items-center gap-6">
<a
href="/signup"
className="rounded-md bg-accent px-6 py-3 font-medium text-white transition-colors hover:bg-accent/90"
>
Run your first close free
</a>
<a
href="/demo"
className="text-sm font-medium text-ink underline-offset-4 hover:underline"
>
Watch the 2-min demo →
</a>
</div>
<p className="mt-10 text-sm text-zinc-500">
Free for the first close. No card. SOC 2 Type II.
</p>
</div>
<div className="relative hidden lg:block">
<img
src="/close-dashboard.png"
alt="Month-end close dashboard showing 3 open exceptions"
className="rounded-xl border border-zinc-200 shadow-2xl"
width={720}
height={480}
/>
</div>
</div>
</section>
);
}The gut-check: cover the logo and the URL. Could you tell, in three seconds, which product this is and what it does? The BEFORE could have been anyone selling anything. The AFTER could only be a month-end close tool for finance teams — and that's the entire game. Specificity is the watermark a generator can't forge.
None of these eleven edits was clever. No new library, no animation, no design talent required — just eleven refusals to accept the default. That's the whole method: the slop isn't in the code, it's in the eleven decisions nobody bothered to make.
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.