Landing page

Hero, features, CTA — the standard parts.

9 mineasy

The landing page is the first thing a customer sees. Three sections, a clear value prop, a CTA. This lesson is about shipping a respectable landing page in 30 minutes — not perfecting it.

The standard parts

  • Hero — headline, sub-headline, primary CTA
  • Social proof — logos, testimonials, stats
  • Features grid — three to six benefit-led items
  • Pricing / final CTA
  • Footer — links, social, copyright

The hero — server component, no JS needed

apps/web/app/(marketing)/page.tsx
import Link from 'next/link'
export default function HomePage() {
return (
<>
<section className="py-24 text-center">
<h1 className="text-5xl font-bold tracking-tight max-w-2xl mx-auto">
Run your retail business from one place
</h1>
<p className="mt-4 text-lg text-muted-foreground max-w-xl mx-auto">
POS, inventory, reports — built for shops with 1 to 50 outlets.
</p>
<div className="mt-8 flex justify-center gap-3">
<Link href="/signup" className="rounded-full bg-primary px-6 py-2.5 text-primary-foreground">
Start free trial
</Link>
<Link href="/demo" className="rounded-full border px-6 py-2.5">
See a demo
</Link>
</div>
</section>
<FeaturesGrid />
<SocialProof />
<FinalCTA />
</>
)
}

Server component by default. No "use client" at the top. HTML ships pre-rendered; bundle stays tiny.

The features grid

function FeaturesGrid() {
return (
<section className="py-20 grid grid-cols-1 md:grid-cols-3 gap-8">
{FEATURES.map((f) => (
<div key={f.title} className="rounded-xl border p-6">
<f.icon className="h-6 w-6 text-primary" />
<h3 className="mt-3 text-lg font-semibold">{f.title}</h3>
<p className="mt-1 text-muted-foreground">{f.body}</p>
</div>
))}
</section>
)
}
const FEATURES = [
{ icon: Zap, title: 'POS in 5 seconds', body: 'Scan, total, print receipt. No training needed.' },
{ icon: Box, title: 'Inventory that just works', body: 'Re-order alerts, multi-location, batch tracking.' },
{ icon: BarChart, title: 'Reports out of the box', body: 'Daily, weekly, year-over-year. Export to Excel.' },
]

Why server components win for landing pages

  • No hydration cost. The user gets HTML; the JS bundle is minimal. Lighthouse loves it.
  • SEO-friendly out of the box. Bots see the content directly.
  • Can fetch at request time. Stats, latest testimonials — fetch in a server component, render to HTML.
Keep interactivity isolated — make the "Get started" button a plain <Link>, the dark-mode toggle a small client component. The page stays mostly static.

Reusable hero pattern

Pull the hero into components/hero.tsx so other marketing pages (about, pricing, blog index) can reuse it. Pass { title, subtitle, ctaHref, ctaText } as props.

Quick check

A teammate adds `'use client'` to apps/web/app/(marketing)/page.tsx because they want to add a counter animation in the hero. What's the lighthouse impact?

Try it

Build a real landing page on your scaffolded project:

  1. Replace apps/web/app/(marketing)/page.tsx with hero + features grid + final CTA.
  2. Add at least three feature items, real product-y copy.
  3. Open localhost:3000 — verify it looks like a product page, not a default Next template.
  4. Run Lighthouse on it (Chrome DevTools → Lighthouse → Performance). Aim for ≥90.

Paste your Lighthouse score in notes.md.

What's next

Last lesson of this chapter — SEO + Open Graph. Make your page discoverable and shareable.

Spot a typo? Have an idea?

Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled — suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.

Suggest an improvement on GitHub