Colophon
The art direction, the techniques, and the workflow behind the redesign, written down so you can borrow whatever is useful.
The direction
A personal site earns cohesion from one committed idea, not from a different trick per page. The idea here: a naturalist's field journal. Digital gardens grow; field journals record the growing. So the pages are chapters, the metadata is set like a specimen label, the dividers are fleurons, and the ornaments are drawn from botany and navigation rather than from tech-brand gradients.
Light mode reads as morning paper. Dark mode is the same garden at dusk. Both share a single ember accent, so switching themes feels like the light changing, not the site changing.
The palette
paper-50
page, light
ink-900
text, light
dusk-950
page, dark
cream-100
text, dark
ember-500
accent
ember-400
accent, dark
moss-600
botanical
moss-400
botanical, dark
All colour lives in a Tailwind v4 @theme block as OKLCH, so lightness steps stay perceptually even and the ember reads equally warm on paper and on dusk.
The type
Aa Qq &
Fraunces · display · SOFT 45, WONK 1
Long-form text is set in Newsreader, a face drawn for reading on screens at book-ish sizes. Italics carry the asides.
Newsreader · body & italics
ANNOTATIONS, DATES & SPECIMEN LABELS
JetBrains Mono · metadata
The techniques
A living shader atmosphere
The background is a full-viewport fragment shader written by hand against raw WebGL1: domain-warped fbm noise breathing through the palette, a lantern glow that trails the pointer, and ember fireflies that drift upward at dusk. Theme changes crossfade inside the shader. No three.js; the whole thing is one component and ~120 lines of GLSL, and the CSS wash beneath remains the no-WebGL fallback.
Type choreography
Mastheads arrive glyph by glyph: each character rises out of the baseline with a touch of rotation and blur on a long expressive ease. The spans are rendered on the server with per-glyph delays, grouped into nowrap word spans so headings still wrap correctly, and the real text lives in an aria-label.
Scroll-driven CSS animations
Every reveal is scrubbed by the browser's own scroll timeline: animation-timeline: view() for entrances, scroll() for the reading-progress hairline and the parallax ferns on the home masthead. No IntersectionObserver, no scroll listeners. Browsers without support simply show the content.
Generative botanical line art
The ferns are not images. They are geometry computed in a Server Component: a quadratic bezier stem, leaflets placed by sampling the curve and rotating away from its tangent. Each path carries pathLength="1" so a one-line CSS animation draws it stroke by stroke.
A hand-rolled expedition globe
The travel page carries a wireframe earth written against raw WebGL: every visited city plotted as an ember point from its coordinates, someday places as moss rings, and flight arcs out of Auckland with a light pulsing along each route. Drag it and it spins with inertia. Two small shader programs, geometry built once in JavaScript, still no 3D library.
An armillary sphere in pure CSS
Eight bordered divs in a preserve-3d scene, spun by a single keyframe: readable, lightweight 3D without a polygon in sight. It appears at the end of this page, and stands in for the globe wherever WebGL is unavailable.
Motion with weight
Pointer interactions run on lagged lerps, the physics trick behind most award-site feel: a cursor ring that trails the mouse and swells over links, and photo tiles that tilt toward the pointer like prints picked up from a desk. Mouse only; touch users get the plain interface.
Departures and arrivals
A template.tsx remounts on every navigation, so each route plays a quiet entrance instead of snapping in. The home page also carries a slow specimen-tape marquee, the journal's one concession to pure ornament.
Variable fonts, self-hosted
Fraunces carries its optical-size, SOFT and WONK axes in one latin-subset file, so the same font renders both the wonky display masthead and quiet headings. Newsreader handles long-form text, JetBrains Mono the annotations. Five woff2 files, about 590 KB, preloaded where they matter.
An OKLCH palette
Warm paper and ink for daylight, dusk and cream for night, one ember accent shared by both. OKLCH keeps perceived lightness honest across hues, which is what makes the two themes feel like the same room at different hours. Film grain from an inline feTurbulence filter dithers everything into one texture.
Server Components by default
The ferns, the sphere, the rotating phrase, the choreographed type and all the reveals are server-rendered markup animated by CSS. Client JavaScript is reserved for what genuinely needs it: the shader canvas, the globe, the cursor ring, the theme toggle, the mobile menu, active-nav state, and the photo lightbox.
Motion that asks permission
Every animation, from the shader to the marquee, lives behind prefers-reduced-motion: no-preference. With reduced motion on, the site is fully drawn and fully readable; nothing depends on an animation having run.
The workflow
Audit
Read every route, component, and token of the existing site before touching anything. The redesign had to preserve the content, the stack, and the Server Component discipline.
Direction
One idea, committed to fully: a naturalist's field journal. The site is called a digital garden, so the design finally acts like one. Warm paper, ink, an ember accent, botanical line work, chapter numbering.
Tokens first
Palette, type scale, and motion vocabulary went into globals.css before any page was rebuilt. Every route then drew from the same small kit: annotation labels, fleuron rules, stat blocks, reveal classes.
Rebuild every route
Home, both notebooks, the article template, travel, about, photos, and this page, each composed from the shared kit so the site reads as one body of work rather than a gallery of experiments.
Iterate with fresh eyes
Three full passes across every page in both themes and at mobile width: hunting weak spacing, cheap motion, broken pairings, and contrast failures, then refining.
Everything above ships with zero new dependencies: the stack is still Next.js 15, Tailwind v4, and MDX, exactly as it was before the redesign. Both WebGL pieces are hand-written GLSL against the raw browser API, and the only borrowed artwork is the set of flag SVGs from the MIT-licensed flag-icons project.