Next.js 15 + Tailwind v4 implementation of the design spec in design.md.
npm install
npm run devOpens at http://localhost:3000.
| Layer | Choice |
|---|---|
| Framework | Next.js 15 (App Router) |
| Styling | Tailwind v4 (@theme CSS-first tokens in app/globals.css) |
| Animation | GSAP + ScrollTrigger, Lenis, Framer Motion |
| Fonts | next/font — Inter; Söhne Breit slot ready for localFont({ src }) |
app/
globals.css — §02–§05 token system, @theme, utilities
layout.tsx — Nav + Footer + SmoothScroll wrapper
page.tsx — Homepage (§08)
services/ — index + [slug] detail
work/ — index + [slug] detail
about/
contact/
components/
Nav.tsx / Footer.tsx / SmoothScroll.tsx
ui/ — Button, Container, Reveal primitives
home/ — 11 homepage sections (Hero → QuoteForm)
lib/utils.ts — cn(), phone/email constants
Everything lives in app/globals.css under @theme. Tailwind v4 reads these
directly — no tailwind.config.ts required. Components reference tokens as
var(--color-ink), var(--ease-default), etc.
- Hero — scroll-scrubbed video (
components/home/Hero.tsx). GSAP ScrollTrigger pins the section, drivesvideo.currentTimefrom scroll progress. Drop a Mux/Cloudflare Stream source into the<video>element to activate. A CSS poster gradient is shown until then. - Process — 6-step pinned sequence with cross-fades and a progress rail.
- Exposure picker — four-tile educator with hover/tap driving the sample.
- Gallery — inertial horizontal scroll, per-frame centre-scale.
- Before / After — draggable divider with keyboard + pointer support.
- License Söhne Breit, drop
.woff2into/public/fonts, wire vianext/font/localinapp/fonts.ts. - Replace placeholder gradient cards with
next/imageonce photography is shot (aspect ratios already declared — zero CLS on swap). - Host the hero finish-reveal video on Mux or Cloudflare Stream.
- Wire
QuoteForm.submitto a Server Action → Resend + Notion/Airtable. - Add Sentry, Vercel Analytics + Plausible.
- Run Lighthouse against §11 budgets before launch.