Skip to main content

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
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

Last build: 82ceb7c · 12 Jun 2026

Coordinates: 51.5074° N · 0.1278° W