Colophon · v.82ceb7c
Notes on the make.
A studio site is also a portfolio of choices — every typeface, easing curve and dependency is a small editorial decision. This page is the long version of those decisions: what we used, why we used it, and who we owe.
01 / Typography
Two voices, one register.
Type is the loudest design choice on a digital studio site. We picked one family that does the work of three: Geist for headlines and body (Vercel’s sans, neutral but architectural across the wght axis), with Geist Mono for labels, code and metadata (so the editorial chrome reads as a system, not a flourish).
- Headings
- Geist 700 / 800Vercel
- Body
- Geist 400 / 500Vercel
- Mono
- Geist Mono 400Vercel
- Loading
- next/font/google with display: swap
02 / Foundation
React + Next, on the bleeding edge.
Next.js 16 (App Router, React Server Components, streaming metadata, Turbopack), React 19 with Activity + ViewTransition hooks, TypeScript everywhere. We treat upgrades as table stakes — running the latest stable surfaces breaking changes early and keeps the studio fluent in the framework we ship for clients.
- Framework
- Next.js 16.2.2App Router · RSC · Turbopack
- Runtime
- React 19.2 / TypeScript 5
- Linting
- ESLint flat config + react-hooks rules
- Source
- TS strict, no any allowed
03 / Styling
Tailwind v4, but with intent.
Utilities for layout, CSS variables for tokens. Tailwind v4’s @theme directive keeps every brand colour, font and fluid-type clamp in one globals.css file — so when we redesign the system, every component picks it up without touching them.
Inline style={} is preferred for design-system tokens (so reviewers can grep for var(--accent)); utilities own the layout grid.
- Engine
- Tailwind CSS v4
- Tokens
- @theme in globals.cssSingle source of truth
- Type scale
- Fluid clamp() — xs → display
- Accent
- #6366F1 · indigo
- Radius
- xl: 12 · 2xl: 16 · full: pills
04 / Motion
A coreography in three layers.
Different motion engines for different jobs. Lenis runs the base scroll loop with rAF integration. GSAP drives the heavier orchestration — pinned theatres, ScrollTrigger timelines, the page-transition curtain, our shared-element FLIP morph from project card to case-study hero. Framer Motion handles small local-state transitions where co-locating with React is more ergonomic than imperative tweening.
Every animation is gated behind prefers-reduced-motion. The system respects that signal in capture-phase, before any timeline starts.
- Scroll
- Lenis 1.3
- Engine
- GSAP 3.14 + ScrollTrigger / Flip / SplitText
- Local
- Framer Motion 12
- Transitions
- Custom variant systemmorph / fade / curtain
05 / Three dimensions
WebGL, used surgically.
Three.js for the WebGL effects (custom cursor field, particle void on the 404 page, ambient image distortions). React Three Fiber where the scene is component-shaped; raw Three where the shader needs imperative control. Everything WebGL is gated on tier detection — we never ship it to laptops that can’t run it cleanly at 60fps, and never to prefers-reduced-motion users.
- Engine
- Three.js 0.183
- React
- @react-three/fiber 9 + drei 10
- Loading
- next/dynamic, ssr: false
- Tiering
- GPU + connection check before mount
06 / Sound design
Synthesis, not samples.
The optional ambient drone you hear when you toggle sound on isn’t a file — it’s three oscillators layered at C2, G2, and C3, routed through a low-pass filter at 600 Hz with a slow LFO modulating the gain. No audio assets ship in the bundle.
Hover, click and transition cues are the same: short synthesized tones with envelopes shaped per event. Every sound respects the global mute state and prefers-reduced-motion.
- Engine
- Web Audio API · OscillatorNode
- Notes
- C2 (65.4 Hz) · G2 (98 Hz) · C3 (130.8 Hz)
- Filter
- Lowpass · 600 Hz · LFO 0.25 Hz
- Gain
- 0.04 target · click to mute
07 / Data + auth
Supabase, with RLS first.
Supabase Postgres for the database, Supabase Auth for client accounts. Every table is row-level-secured — no public reads of user data, no service-role keys in the client. The @supabase/ssr package handles cookie-based sessions in the App Router so the same query works in Server Components, Route Handlers and Server Actions.
- Database
- PostgreSQL · Supabase
- Auth
- Supabase Auth · Google OAuth + email
- Security
- RLS on every user table
- Migrations
- SQL files in supabase/migrations
08 / Payments
Stripe, retainer-shaped.
Stripe Subscriptions for the three retainer tiers. Webhook handlers reconcile subscription state to Supabase, so the dashboard’s entitlement check never depends on a live API call. Customer portal handles upgrades, downgrades and cancellations without us building a billing UI.
- API
- Stripe 22.x · 2026-03-25.dahlia
- Model
- Subscriptions · monthly billing
- Tiers
- Foundation £1,500 · Acceleration £3,500 · Scale £7,500 · Bespoke from £10,000
- Webhooks
- /api/webhooks/stripe with signed verification
09 / Email
Resend for everything transactional.
Contact-form submissions, dashboard welcome emails, newsletter audience management — all via Resend. Stripe handles invoice emails directly so we don’t duplicate that path. No SMTP, no sub-Postmaster files to maintain, no SPF/DKIM copy-pasting.
- Provider
- Resend 6.x
- Audiences
- Newsletter list via Audiences API
- Templates
- JSX-rendered, no MJML
- Limits
- 5 contact / 5 newsletter / IP / hour
10 / Hosting + build
Vercel, edge where it counts.
Vercel hosting, GitHub for source. Each commit on main deploys automatically to production; preview deploys land on every branch and pull request. Build runs in parallel across 17 workers, generates 93+ static pages including OG images and sitemap, finishes in under three minutes.
- Host
- Vercel
- CI/CD
- Auto-deploy on push to main
- Edge
- Image optimisation, OG generation
- Source
- GitHub · private repository
11 / Observability
Three lenses, no personal data.
Plausible for referrers and event tracking — no cookies, no cross-site identifiers, GDPR-clean by default. Vercel Analytics for deployment-aware page views (useful when comparing before/after a release). Vercel Speed Insights for real-user Core Web Vitals per route. Together they’re enough to make decisions; no individual visitor is ever tracked.
- Page views
- Plausible · cookieless
- Deploys
- Vercel Analytics
- CWV
- Vercel Speed Insights
- Errors
- Vercel runtime logs
12 / Influences
Studios that taught us how.
No design happens in a vacuum. The editorial micro-labels owe a debt to Frank Chimero and Naomi Atkinson; the cinematic transitions to studios like Resn, Locomotive and Ueno; the type-as-architecture instinct to Wim Crouwel and any classic Swiss spread you’ve ever seen.
On the engineering side: Lee Robinson and the Vercel docs are still the clearest writing on Next.js architecture. Josh Comeau’s posts shaped how we think about animation ergonomics. Andy Bell on layout primitives.
- Editorial
- Chimero · Atkinson · Mall
- Motion
- Resn · Locomotive · Ueno
- Engineering
- Lee Robinson · Josh Comeau · Andy Bell
- Sound
- Brian Eno · William Basinski
13 / Standards
What we won't ship without.
Standards are commitments, not check-marks. Every page passes WCAG AA contrast, has visible keyboard focus, respects prefers-reduced-motion, ships under a 2.5s LCP target on a mid-tier mobile, and renders without JavaScript for the marketing surfaces. The free /audit tool is the one we run on our own work first.
- A11y
- WCAG AA · keyboard nav · ARIA
- Perf
- LCP < 2.5s · TBT < 200ms target
- SEO
- JSON-LD · sitemap · canonical URLs
- Privacy
- No third-party trackers without consent
14 / Source
Where this lives.
The repository is private — but if you’re curious about a specific pattern, ask. We’re happy to walk through the transition system, the OG generator, the audio engine, the Stripe / Supabase glue, or anything else by email or on a call.
For a live snapshot of what’s being worked on, see /now. For recent shipping notes, see /changelog.
- Build
- 82ceb7c12 Jun 2026
- Latest
- See /changelog
- Live
- See /now
- Contact
- hello@gosmartr.co.uk
15 / Mark
The R is raised.
The mark is engineered, not picked. The wordmark is set in Geist SemiBold outlines — the family the whole site reads in — cut to vectors with a parametric build, with a raise tick under the final R as the only device. The construction is documented end to end: outline extraction, build scripts, three rendered calibrations, full-resolution verification.
Before it shipped we ran reverse-image clearance: TinEye returned zero matches across 84.5 billion indexed images, and Google Lens surfaced no construction twin (2026-06-11).
- Wordmark
- Geist SemiBold outlines · tracking −8/emcustom-cut vectors, never font text
- Device
- Raise tick under the final Rtick height 75 · gap 100 · R ink width
- Ink
- #FAFAFA on dark · #0A0A0A on light · #6366F1 accent
- Clearance
- TinEye 0 / 84.5B exact · Lens no construction twin2026-06-11
08 / Hidden corners
Some things are off the menu.
A studio site should reward curiosity. A handful of mechanisms are intentionally undocumented in the visible UI — discoverable through the keyboard, the DevTools console, or just clicking the right thing the right number of times. None of them gate functionality; all of them say something about how we’d build for you.
The terminal’s secret command is the in-context version of this list — open the terminal with ` (backtick) and type it.
- ⌘K
- Search palettefull-content search
- `
- Terminal modetype `help` to start
- ⌘⇧D
- Developer modelive FPS · Web Vitals
- ⌘⇧S
- Spec modedesign X-ray · type scale · grid
- Shift × 3
- Ghost modedesaturated world for 4s
- Konami
- Rainbow accent↑↑↓↓←→←→BA
- 7 × logo
- Credits modalthe people behind it
- DevTools
- Console signaturestudio mark + door list