We rebuilt this site from scratch in early 2026. Not because the old one was broken \u2014 it converted fine \u2014 but because we kept ending pitches with “you should see what we’re capable of” and pointing at someone else’s work. The site you’re reading is the answer to that.
It’s also the longest single project we’ve shipped for ourselves, and the one we learned the most from. This post documents the choices, the hard parts, and the opinionated bits we’d pick again.
The stack
We picked a stack that we already use on most client work, with one deliberate exception: we let ourselves over-engineer the interactions. The studio site is the place we test the patterns we eventually ship for clients.
- Framework
- Next.js 16 (App Router) · React 19
- Language
- TypeScript
- Styling
- Tailwind v4 · CSS variables for tokens
- Animation
- GSAP · Framer Motion · Three.js / R3F
- Smooth scroll
- Lenis
- Auth + DB
- Supabase
- Payments
- Stripe (Checkout + Customer Portal)
- Resend (transactional + Audiences)
- Analytics
- Plausible (cookieless)
- Hosting
- Vercel
The design system
Everything visual is driven by CSS custom properties, declared once in src/styles/globals.css under a Tailwind v4 @theme. That single source of truth made the “page mood” system possible: each route can tint the accent hue and the ambient gradients without touching a component.
Type
Three families: Syne for headings, Inter for body, JetBrains Mono for editorial labels and code. Sizes scale fluidly with clamp() from --text-xs through --text-display \u2014 no breakpoint juggling for type.
Color
A monochrome dark base anchored by one accent: lime #C8FF00. Used sparingly. Most of the page is foreground and background; the accent appears for status pills, focus rings, the FinalTheater underline, and very little else.
The theatre layer
The signature pattern across this site is scroll-driven theatre: long sections that pin to the viewport and scrub through 2\u20133 stages as you scroll.
The home page closes with the FinalTheater \u2014 a three-act pinned scene with the question, a live status panel (London time, bookings, latest launch), and the invitation. Case study pages have their own pinned testimonial moment and an editorial chrome (Vol. marker, ghost numerals, live URL pill). The result is that scrolling through the site feels like flipping through a magazine, not a marketing slide deck.
The site is a portfolio, but it should feel like a magazine.
— Working principle
The performance budget
Every interaction has a fallback. The hero ambient layer is a single CSS keyframe stack; the WebGL particle field is gated on hardware tier and reduced-motion. Lenis smooth scroll is wrapped so any visitor with prefers-reduced-motion: reduce gets native scroll. The point is that the “wow” moments never gate accessibility.
What’s next
The journal you’re reading is the next layer. Then a deeper /studio dashboard with live commit data, then probably a sandbox page where visitors can mess with the same primitives we used to build this. We’ll write about each as we ship them.
If you’ve made it this far and want a similar build, the scope calculator on /pricing will give you a quick range. Or just come and say hello.