Back home

Colophon

How I built this site

Some notes on the stack, decisions I made along the way, and a few small details that are easy to miss!

Stack

  • Next.js 15 with the App Router
  • TypeScript with strict mode on
  • Tailwind CSS with CSS variables for the design tokens
  • Framer Motion for the animations
  • Lenis for smooth scrolling on desktop
  • Geist Sans, Geist Mono, and Instrument Serif for the type
  • Deployed on Vercel

Notes

Started with design tokens

Color, type, spacing, and motion easing all live as CSS variables. Tailwind points to them, so changing one variable updates the whole site.

Motion stays quiet

Nothing animates unless it actually adds something to the experience. Every animation also has a still fallback for users who prefer reduced motion. Smooth scroll only kicks in on desktop, never on mobile.

Content lives as typed data

Projects, experience, socials, and the Currently block all live as typed files in src/lib/data. Adding a new project is a one file edit, no component changes needed!

Server components by default

Most of the site is rendered on the server. Only the pieces that need browser APIs or motion are client components. The heavy shader background loads in dynamically with a CSS fallback underneath, so the page never has to wait on it.

Little details

  • The italic word in the hero cycles between good, useful, fast, calm, honest, and durable. The rest of the line stays still while it animates.
  • Some gradient blobs drift slowly behind the hero. All pure CSS, no WebGL needed!
  • The Contact email pulls toward your cursor when you get close to it.
  • The Now pill next to my current role pulses slowly, so you can tell at a glance what's still active.
  • Click into a project and its cover image rides the transition with you. No jump between pages.

You can find the source over on GitHub →