Live site: kevinmurphywebdev.com
Source: github.com/midimurphdesigns (private — happy to share the brand-system + ADR docs on request)
The site you're reading. Built by hand on Next.js 16's App Router with React Server Components, Tailwind v4's CSS-first design tokens, MDX-driven content, and a programmatic resume rendered from a single JSON source of truth. 95+ Lighthouse on desktop across all four scores. Per-build PDF export of the resume so the downloadable file can never drift from the live page.
How it's built
Server Components by default — "use client" only appears where it's required (cursor, smooth scroll, demo subdomains). Tailwind v4's CSS-first config sits in app/globals.css via @theme, so design tokens are the source of truth for both runtime CSS and tooling that needs to read them. No tailwind.config.js. Three-tier type hierarchy locked in an ADR (Migra italic for display ≥32px, Space Grotesk for body, Geist Mono for metadata). Single cyan accent on near-black canvas; no glass, no gradient mesh, no card grid. The resume page reads from one resume.json file; a postbuild Puppeteer hook re-renders the live /resume route as a PDF on every Vercel deploy, so the download is always the live page.
Artifacts worth reading
- The decisions log (28+ ADRs covering type system, motion, color, resume export, demo subdomains)
- The three hosted demo subdomains: grant-pilot, fedbench, fieldops-mcp
- The site's own /demos index and /blog feed
The trade-offs
Hand-building every primitive — KMLogo, Cursor, Hero, Header, the resume renderer, the OG-image route — takes longer than dropping a template. The trade is that nothing on the site is a vendor's idea of how it should look. It's a place I can iterate on without fighting somebody else's defaults.