Under the Hood
About This Site
The stack behind this site, from the components on screen to the data sources behind them.
View the source on GitHub (opens in a new tab)The Stack
Frontend
React
The UI library behind every component on the site, from the navbar to a single badge.
TanStack Router
Type-safe, file-based routing: each route file in src/routes becomes a page, and the router plugin generates the route tree and splits each page into its own bundle.
Tailwind CSS
Styles every page. The synthwave palette, glow shadows, and grid backgrounds are custom theme tokens and utilities in index.css.
shadcn/ui
Accessible primitives built on Base UI (Dialog, Popover, Navigation Menu) plus Card, Badge, and Input, copied into src/components/ui and themed to the palette.
Data Sources
Notion
The board game collection. The Games page calls api/games.ts, which reads Notion live behind a 5-minute edge cache; if that call fails, the page falls back to a snapshot checked into the repo.
Neon
Serverless Postgres holding the minerals & fossils catalog, queried by api/fossils.ts. Schema changes are versioned in db/migrations.
Hardcover
The reading library behind the Books page, from Hardcover's GraphQL API via api/books.ts and api/currently-reading.ts. Fetched live behind a short edge cache, with no database of its own.
Spotify
My listening data on the Music page, from the Spotify Web API. api/spotify.ts caches its access token in memory until shortly before it expires, fetches each section in parallel, and serves the result behind a short edge cache.
BoardGameGeek
Box art, ratings, and other game details. A local script (npm run sync:bgg) copies them into Notion, so the site never calls BoardGameGeek's API; box art loads straight from BoardGameGeek's image CDN.
Infrastructure & Tooling
Vercel
Hosts the site and builds every push. The api/ folder runs as serverless functions for games, fossils, books, currently reading, and Spotify.
Vercel Blob
Stores the full-size minerals & fossils photos. Each specimen's row in Neon holds its photo's Blob URL.
wsrv.nl
An image resizing proxy that makes the thumbnail and medium versions of the fossil photos on request, so Blob only stores one original per photo.
Vitest
Runs the test suite as the first step of every build, so a failing test stops the deploy.
jsPDF
Generates the downloadable resume PDF in the browser from resume-data.ts, the same data the Resume page renders.
Claude Code
How most of the site is built, with an orchestrator agent and a custom design skill. See How I Build With AI below.
Data Flow
Vercel's serverless API routes branch out to four data sources at request time: Notion, Neon, Hardcover, and Spotify. Only the minerals & fossils path touches image storage: its photos live in Vercel Blob and are resized by wsrv.nl. BoardGameGeek details are copied into Notion ahead of time by a local sync script, and box art loads straight from BoardGameGeek's image CDN.
Build & Deploy
Every push runs the same Vercel build: tests, a type check, the RSS feed, the production build, then a prerendered HTML page per route. The branch alone decides whether it lands as a preview or goes live.
How I Build With AI
This site, and most of what's on it, is built with Claude Code. Work gets scoped and planned up front, then handed to subagents that implement and review in a loop until it holds up, before a PR ever opens.
Larger features go through an orchestrator agent (.claude/) that breaks the work into steps and hands them one at a time to specialized subagents for architecture, implementation, and design, with a review agent checking each step's changes and sending fixes back until they pass. A custom design skill, synthwave-ui (.claude/), keeps the palette and styling consistent from page to page.
I built this site to learn how to work with AI, skills, MCPs, and other tools. I wanted to see how far I could get without writing the code myself, focusing instead on understanding agentic workflows, and to find out how effective I could be building a site this way.