Skip to content

Reference · website

Section archetypes

website/references/section-archetypes.md374 linesupdated 16 Sept 2026

Skeletons use the template primitives and void tokens. Copy, then replace content with real content from src/content/*. All are Server Components unless marked.

tsx
import Image from "next/image";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Container } from "@/components/ui/container";
import { Eyebrow } from "@/components/ui/eyebrow";
import { Section } from "@/components/ui/section";
import { TextLink } from "@/components/ui/link";
import { cn } from "@/lib/cn";

Rules for every section: one job; left-aligned unless noted; heading max-w-[Nch]; eyebrows on ≤ 1/3 of sections; adjacent sections differ in archetype and rhythm.


1. Heroes

Measured patterns (24 sites): left H1 + short sub + 1–2 CTAs then real product (Linear, Cursor, Framer); split H1 left / paragraph right (Anthropic, Supabase); centered with product UI (Attio, Clerk, Railway); poster/type-as-image (Granola, Dia, hellohello). Headers 56–72px; H1 46–96px desktop; sub 18–24px, max 480–672px.

1a. Editorial left (default when there's no strong visual)

tsx
<section aria-labelledby="hero-title" className="grain relative overflow-clip border-b border-line-subtle">
  <Container className="pt-16 pb-20 sm:pt-24 lg:pt-36 lg:pb-28">
    <Eyebrow>Open source · MIT · v3.2</Eyebrow>
    <h1 id="hero-title" className="mt-6 max-w-[15ch] text-display-xl text-fg">Feature flags that live in your repo.</h1>
    <div className="mt-8 grid gap-8 lg:grid-cols-12">
      <p className="max-w-[46ch] text-lg text-fg-muted lg:col-span-6">
        Flags are YAML next to the code they gate. Reviews, rollbacks and audit history come from git, not a dashboard.
      </p>
      <div className="flex flex-wrap items-center gap-6 lg:col-span-6 lg:justify-end lg:self-end">
        <Button href="/docs/quickstart" size="lg">Read the quickstart</Button>
        <TextLink href="https://github.com/acme/flags" tone="muted" className="font-mono text-sm">github.com/acme/flags</TextLink>
      </div>
    </div>
  </Container>
</section>

1b. Product shot (UI is the proof)

tsx
<section aria-labelledby="hero-title" className="relative overflow-clip">
  <div aria-hidden="true" className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-144 bg-[radial-gradient(60%_70%_at_20%_0%,color-mix(in_oklch,var(--brand)_12%,transparent),transparent_70%)]" />
  <Container className="pt-16 lg:pt-28">
    <div className="flex flex-wrap items-end justify-between gap-6">
      <h1 id="hero-title" className="max-w-[16ch] text-display-lg text-fg">Deploy previews for every branch in 14 seconds.</h1>
      <TextLink href="/changelog" tone="muted" className="text-sm">New · Rollback from Slack →</TextLink>
    </div>
    <p className="mt-6 max-w-[44ch] text-lg text-fg-muted">Push a branch, get a URL. Logs, env and rollbacks live on the same page.</p>
    <div className="mt-8 flex flex-wrap gap-3">
      <Button href="/signup" size="lg">Start deploying</Button>
      <Button href="/demo" size="lg" variant="secondary">Book a demo</Button>
    </div>
    <figure className="mt-14 lg:mt-20">
      <div className="overflow-clip rounded-2xl border border-line bg-surface shadow-3">
        <Image src={deployShot} alt="Deploy view listing three branch previews with build times" sizes="(min-width: 1280px) 1136px, 100vw"
          fetchPriority="high" loading="eager" className="h-auto w-full" />
      </div>
    </figure>
  </Container>
</section>

Frame rules: real UI, no browser chrome, no glow, no tilt. On mobile crop to the most legible region (object-left-top in a fixed aspect-[4/3] box) instead of shrinking.

1c. Typographic poster (voice-led, agency, launch)

tsx
<section aria-labelledby="hero-title" className="relative min-h-[80svh] border-b border-line">
  <Container className="flex min-h-[80svh] flex-col justify-between pt-10 pb-10">
    <div className="flex justify-between label-mono text-fg-muted">
      <span>Studio Norte</span><span>Montevideo · est. 2014</span>
    </div>
    <div>
      <h1 id="hero-title" className="sr-only">Studio Norte — brand and product design studio in Montevideo</h1>
      <p aria-hidden="true" className="text-[clamp(3rem,1.2rem+6.2vw,6.75rem)] leading-[0.9] [font-weight:var(--weight-display)] tracking-[-0.03em] text-fg">
        Brands that<br />look like<br /><span className="text-fg-muted">nobody else.</span>
      </p>
      <p className="mt-8 max-w-[40ch] text-lg text-fg-muted">Identity, product and web for 41 companies since 2014.</p>
    </div>
    <div className="flex items-end justify-between label-mono text-fg-subtle"><span>(Scroll)</span><span>Selected work ↓</span></div>
  </Container>
</section>

One semantic

(visually hidden is fine), the visual lockup aria-hidden. Test the lockup at 320px.

1d. Split (H1 needs nuance beside it)

tsx
<Container className="grid gap-10 border-b border-line-subtle pt-16 pb-16 lg:grid-cols-12 lg:pt-32 lg:pb-24">
  <h1 className="text-display-lg text-fg lg:col-span-7">Postgres with branching, for teams that ship daily.</h1>
  <div className="lg:col-span-5 lg:self-end">
    <p className="text-lg text-fg-muted">Every pull request gets its own database copy in under a second. Schema changes merge like code.</p>
    <div className="mt-6 flex gap-3"><Button href="/signup">Start free</Button><Button href="/docs" variant="ghost">Docs</Button></div>
  </div>
</Container>

Centered variant: only for a ≤ 3-line H1 + ≤ 2-line sub + product UI below (Attio, Clerk). Everything after the hero goes back to left-aligned.

2. Proof strip / logo wall (only real, permitted logos)

tsx
<section aria-label="Customers" className="border-b border-line-subtle py-10 lg:py-12">
  <Container className="grid items-center gap-8 lg:grid-cols-12">
    <p className="text-sm text-fg-muted lg:col-span-3">Runs production deploys for 1,200 teams, including</p>
    <ul className="grid grid-cols-3 items-center gap-x-10 gap-y-6 text-fg-subtle sm:grid-cols-6 lg:col-span-9">
      {logos.map((l) => (
        <li key={l.name} className="flex justify-center"><l.Svg aria-label={l.name} role="img" className="h-5 w-auto" /></li>
      ))}
    </ul>
  </Container>
</section>
  • 4–8 logos, SVG with fill="currentColor", equal optical area (wide wordmarks shorter), no hover color bloom unless brand-mixed.
  • A specific claim beats "Trusted by". No real logos yet → skip the section; do not use grey placeholder logos.
  • Marquee only with 12+ logos and never as the primary proof (components → Marquee).

3. Product showcase (one screen explains the product)

tsx
<Section aria-labelledby="showcase-title">
  <Container>
    <h2 id="showcase-title" className="max-w-[24ch] text-display-sm text-fg">
      One timeline for every deploy. <span className="text-fg-muted">Commits, builds, errors and rollbacks in order.</span>
    </h2>
    <figure className="reveal mt-12 lg:mt-16">
      <div className="overflow-clip rounded-2xl border border-line bg-surface shadow-3"><Image src={timeline} alt="…" sizes="(min-width:1280px) 1136px, 100vw" /></div>
      <figcaption className="mt-6 grid gap-6 text-sm text-fg-muted sm:grid-cols-3">
        <p><span className="text-fg">Build logs</span> stream as they run.</p>
        <p><span className="text-fg">Errors</span> link to the commit that caused them.</p>
        <p><span className="text-fg">Rollback</span> is one click or `/rollback` in Slack.</p>
      </figcaption>
    </figure>
  </Container>
</Section>

4. Feature deep-dive rows (alternating)

tsx
<Section aria-labelledby="features-title">
  <Container>
    <h2 id="features-title" className="max-w-[20ch] text-display-sm text-fg">What changes on day one</h2>
    <div className="mt-16 space-y-24 lg:space-y-32">
      {features.map((f, i) => (
        <article key={f.slug} className="grid items-center gap-10 lg:grid-cols-12">
          <div className={i % 2 ? "lg:order-2 lg:col-span-5 lg:col-start-8" : "lg:col-span-5"}>
            <p className="label-mono text-fg-subtle">{String(i + 1).padStart(2, "0")} · {f.kicker}</p>
            <h3 className="mt-4 text-2xl text-fg">{f.title}</h3>
            <p className="mt-4 text-md text-fg-muted">{f.body}</p>
            <TextLink href={f.href} className="mt-6 inline-block text-sm">{f.linkLabel}</TextLink>
          </div>
          <div className={i % 2 ? "lg:order-1 lg:col-span-7" : "lg:col-span-7"}>
            <div className="overflow-clip rounded-xl border border-line-subtle bg-surface">{/* real UI crop, code, or diagram */}</div>
          </div>
        </article>
      ))}
    </div>
  </Container>
</Section>

2–4 rows. Each visual shows the actual feature, cropped to the relevant 400–600px. Reveal at most the visuals, not the text.

5. Editorial capability list (no visuals, many items)

tsx
<Section aria-labelledby="services-title">
  <Container className="grid gap-10 lg:grid-cols-12">
    <h2 id="services-title" className="text-display-sm text-fg lg:col-span-4">What we do</h2>
    <ol className="divide-y divide-line-subtle border-y border-line-subtle lg:col-span-8">
      {services.map((s, i) => (
        <li key={s.name} className="grid gap-2 py-6 sm:grid-cols-12 sm:gap-6">
          <span className="font-mono text-sm text-fg-subtle tabular-nums sm:col-span-1">({i + 1})</span>
          <h3 className="text-xl text-fg sm:col-span-4">{s.name}</h3>
          <p className="text-md text-fg-muted sm:col-span-7">{s.detail}</p>
        </li>
      ))}
    </ol>
  </Container>
</Section>

The honest replacement for "3 icon cards". Measured on hellohello (numbered rows, 1px rules) and Anthropic.

6. Bento that isn't slop

tsx
<Section aria-labelledby="bento-title">
  <Container>
    <h2 id="bento-title" className="max-w-[22ch] text-display-sm text-fg">Everything the on-call engineer opens at 3 a.m.</h2>
    <div className="mt-12 grid gap-4 lg:grid-cols-6 lg:grid-rows-2">
      <Card className="lg:col-span-4 lg:row-span-2 p-0">{/* biggest tile = most important real UI */}</Card>
      <Card className="lg:col-span-2">{/* real metric or chart */}</Card>
      <Card className="lg:col-span-2">{/* real code or config */}</Card>
    </div>
  </Container>
</Section>
  • 3–6 tiles; spans follow importance; every tile shows something concrete (UI crop, number with unit, code, log).
  • Tile text: text-sm text-fg-muted caption + text-lg text-fg title. No icon-in-circle tiles.
  • Uneven heights → independent columns (flex flex-col gap-4 per column) instead of a stretched row grid.

7. Metrics strip (only measured numbers)

tsx
<section aria-labelledby="numbers-title" className="border-y border-line-subtle py-12 lg:py-16">
  <Container>
    <h2 id="numbers-title" className="label-mono text-fg-muted">Measured on production, Aug 2026</h2>
    <dl className="mt-8 grid grid-cols-2 gap-px overflow-clip rounded-xl border border-line-subtle bg-line-subtle lg:grid-cols-4">
      {metrics.map((m) => (
        <div key={m.label} className="bg-bg p-6">
          <dt className="label-mono text-fg-subtle">{m.label}</dt>
          <dd className="mt-3 text-display-sm text-fg tabular-nums">{m.value}<span className="ml-1 text-xl text-fg-muted">{m.unit}</span></dd>
          {m.source ? <dd className="mt-2 text-xs text-fg-subtle">{m.source}</dd> : null}
        </div>
      ))}
    </dl>
  </Container>
</section>

Numbers need a unit, a date/context and a source you can defend. "99.9% uptime" without a status page is fake.

8. Quote

tsx
<Section spacing="default" aria-label="Customer quote">
  <Container className="grid gap-8 lg:grid-cols-12">
    <figure className="lg:col-span-9 lg:col-start-3">
      <blockquote className="text-3xl text-fg lg:text-4xl">
        <p>“We cut our release checklist from 42 steps to 6. Nobody on the team has opened the old runbook since March.”</p>
      </blockquote>
      <figcaption className="mt-8 flex items-center gap-4 text-sm">
        <Image src={avatar} alt="" width={40} height={40} className="size-10 rounded-full" />
        <span><span className="text-fg">Dana Ortiz</span> <span className="text-fg-muted">· Staff Engineer, Northwind</span></span>
      </figcaption>
    </figure>
  </Container>
</Section>

One long specific quote > a carousel. No star ratings unless they are real reviews with a source (and then seo rules for schema).

9. How it works / install (developer products)

tsx
<Section aria-labelledby="start-title">
  <Container className="grid gap-12 lg:grid-cols-12">
    <div className="lg:col-span-5">
      <h2 id="start-title" className="text-display-sm text-fg">Running in three commands</h2>
      <p className="mt-4 text-md text-fg-muted">No account needed for local use.</p>
    </div>
    <ol className="space-y-6 lg:col-span-7">
      {steps.map((s, i) => (
        <li key={s.cmd} className="grid grid-cols-[2rem_1fr] gap-4">
          <span className="font-mono text-sm text-fg-subtle tabular-nums">{i + 1}.</span>
          <div>
            <p className="text-md text-fg">{s.title}</p>
            <pre className="mt-3 overflow-x-auto rounded-lg border border-line-subtle bg-bg-subtle px-4 py-3 font-mono text-sm text-fg"><code>{s.cmd}</code></pre>
          </div>
        </li>
      ))}
    </ol>
  </Container>
</Section>

Add a copy button as a tiny client island. Code highlighting at build time (Shiki), never a client highlighter (speed).

10. Pricing

tsx
<Section aria-labelledby="pricing-title">
  <Container>
    <h2 id="pricing-title" className="text-display-sm text-fg">Pricing</h2>
    <div className="mt-12 grid gap-px overflow-clip rounded-xl border border-line bg-line lg:grid-cols-3">
      {plans.map((p) => (
        <div key={p.name} className={cn("flex flex-col bg-bg p-6 lg:p-8", p.recommended && "bg-brand-subtle")}>
          <div className="flex items-center justify-between">
            <h3 className="text-xl text-fg">{p.name}</h3>
            {p.recommended ? <span className="label-mono text-brand-text">Most teams</span> : null}
          </div>
          <p className="mt-6 text-display-sm text-fg tabular-nums">{p.price}<span className="ml-1 text-sm text-fg-muted">{p.per}</span></p>
          <p className="mt-2 text-sm text-fg-muted">{p.summary}</p>
          <ul className="mt-6 space-y-2 text-sm text-fg-muted">{p.features.map((f) => <li key={f}>— {f}</li>)}</ul>
          <Button href={p.href} variant={p.recommended ? "primary" : "secondary"} className="mt-8">{p.cta}</Button>
        </div>
      ))}
    </div>
    <p className="mt-6 text-sm text-fg-muted">Prices in USD, excluding tax. <TextLink href="/pricing#compare">Compare every limit</TextLink></p>
  </Container>
</Section>

No scaled-up middle card, no gradient border. Highlight = bg-brand-subtle + label. Full comparison as a real

(page-types.md).

11. FAQ (real objections only)

tsx
<Section aria-labelledby="faq-title">
  <Container className="grid gap-10 lg:grid-cols-12">
    <h2 id="faq-title" className="text-display-sm text-fg lg:col-span-4">Questions teams ask before switching</h2>
    <div className="border-t border-line-subtle lg:col-span-8">
      {faqs.map((q) => (
        <details key={q.q} name="faq" className="void-accordion border-b border-line-subtle py-5">
          <summary className="flex cursor-pointer items-center justify-between gap-4 text-md text-fg">{q.q}</summary>
          <p className="pt-3 text-md text-fg-muted">{q.a}</p>
        </details>
      ))}
    </div>
  </Container>
</Section>

Answers start with the answer ("Yes. …", "Per build minute. …"). Accordion CSS: motion/references/recipes.md §8. Keep the text in the HTML (details content is indexable).

12. CTA band

tsx
<section aria-labelledby="cta-title" className="grain relative overflow-clip border-t border-line-subtle py-24 lg:py-32">
  <Container className="flex flex-col items-start gap-8 lg:flex-row lg:items-end lg:justify-between">
    <h2 id="cta-title" className="max-w-[18ch] text-display text-fg">Your next branch deploys itself.</h2>
    <div className="flex flex-wrap gap-3"><Button href="/signup" size="lg">Start deploying</Button><Button href="/demo" size="lg" variant="ghost">Talk to an engineer</Button></div>
  </Container>
</section>

Repeat the primary CTA label exactly. Centering is acceptable here if the hero was left-aligned.

tsx
<footer className="border-t border-line-subtle pt-16 pb-10">
  <Container>
    <div className="grid gap-10 sm:grid-cols-2 lg:grid-cols-12">
      <div className="lg:col-span-4">
        <Logo className="h-5 text-fg" />
        <p className="mt-4 max-w-[32ch] text-sm text-fg-muted">{site.description}</p>
      </div>
      {columns.map((c) => (
        <nav key={c.title} aria-label={c.title} className="lg:col-span-2">
          <p className="label-mono text-fg-subtle">{c.title}</p>
          <ul className="mt-4 space-y-2 text-sm">{c.links.map((l) => <li key={l.href}><a href={l.href} className="text-fg-muted hover:text-fg">{l.label}</a></li>)}</ul>
        </nav>
      ))}
    </div>
    <div className="mt-16 flex flex-wrap justify-between gap-4 border-t border-line-subtle pt-6 text-xs text-fg-subtle">
      <p>© 2026 Acme, Inc.</p><p className="font-mono">All systems normal</p>
    </div>
  </Container>
</footer>

Only links that exist. Status text only if it's wired to a real status source.


Page composition checks

  • Rhythm alternates dense/airy: hero (airy) → proof (dense, py-10) → showcase (airy, py-24 lg:py-40) → rows (section-y) → metrics (dense) → CTA (airy).
  • Background changes (bg-bg-subtle bands, border-y rules) at most 2–3 times per page.
  • No more than one grid of equal cards on the page.
  • The fold at 1440×900 shows: H1, sub, CTA, and the start of the signature visual. At 390×844: H1 (≤ 3 lines), sub, CTA.