Patine Archive
- YEAR
- 2026
- ROLE
- Designer & Developer
- STACK
- Next.js 16 · React 19 · TypeScript · Tailwind CSS · MDX · anime.js
- LIVE
- Visit ↗

Patine is an editorial wiki for youngtimer cars — the ones that gain value as they age, driven as much as they are admired. It borrows the look of specialist car magazines and the rigour of a manufacturer spec sheet, across a collection of fourteen cars of character: the MX-5 NA, S2000, Corvette C5 and many more. Each gets a fourteen-section sheet — from historical context to buyer's guide, by way of limited editions, the current market and preparation levels.
The challenge
Fit rich editorial writing and a repeatable structure into the same
architecture — no CMS, no backend, no compromise on visual quality. The answer
was to separate the data from the editorial voice. Every car ships as two
files: a typed .ts describing versions, specs, colours, prices, hotspots and
market stats; an .mdx carrying the history, the call-outs, the buying
checklists and the tuning advice. The page itself is purely structural — it
composes the two streams side by side.
Stack
- Framework — Next.js 16.2.6 (App Router, Turbopack, React Server Components by default)
- Language — TypeScript (strict), React 19.2
- Styling — Tailwind CSS with a custom
bone / ink / accentpalette and three type families (Instrument Serif, JetBrains Mono, Inter) - Content — MDX (
@next/mdx,next-mdx-remote/rsc) with a custom section-splitting loader - i18n —
next-intlv4 (FR, with the infrastructure kept for later locales) - Animation — anime.js through three custom hooks, with
prefers-reduced-motionhonoured everywhere - 3D — Sketchfab embeds plus a custom viewer with clickable captions
- Deployment — Vercel (static build with ISR, Vercel Analytics)
Architecture highlights
Colour is data, not styling. Each car carries its accent in its TypeScript
file (accent: "#1A3F8E" for the STi in World Rally Blue). The page sets that
value as a CSS variable on the root <article>, and the whole sheet inherits
it — borders, links, animations, count-ups. No prop drilling, no theme provider.
MDX, section by section. A homemade loader splits each .mdx file on
{/* SECTION: id */} markers and exposes every section as a pluggable
component, slotted at a precise place between the data blocks.
The component map is the design system. The MDX mapping — editorial
headings, accented emphasis, <Lede>, <Callout>, <Checklist>, <ModCard> —
is, on its own, the narrative design system.
One animation vocabulary. A single easing (easeOutCubic), a shared cadence
(60–120 ms stagger, 400–700 ms duration) and three reusable hooks
(useScrollReveal, useCountUp, useTilt). Every component speaks the same
motion language.
Results
- 13 car sheets built on one architecture, each with its own visual identity
- Type-safe end to end — from the registry down to the component
- Fast — static site, lazy-loaded sections, on-demand Sketchfab viewer, loading skeletons
- Accessible —
prefers-reduced-motionon 100% of animations, WCAG-checked contrast, semantic HTML - Migrated Next.js 15 → 16 (Server Components, Turbopack, async APIs,
proxy.ts) with no regressions