Colophon
⟳ tended 1 month ago
Why This Page Exists
Most portfolios show what was built. This page explains why each technical decision was made — and what was traded away. Every choice here is a deliberate constraint, not a default.
This site is a digital garden — an interconnected knowledge graph, not a static portfolio. The architecture reflects that philosophy: everything is linked, everything grows, and every page knows what references it.
Architectural Decisions
Next.js 16 + Static Export
React is my primary professional competency — using it for my personal site is a direct portfolio signal. Static export means zero server cost, zero cold starts, and a site that survives even if I stop paying for infrastructure.
No server-side features (API routes, ISR, middleware). Every dynamic data source needs a creative workaround — build-time scripts or client-side fetches.
GitHub Pages over Vercel
Free, no vendor lock-in, and the deploy pipeline is a simple GitHub Actions workflow I fully control. The site is pure static HTML/CSS/JS — it doesn't need edge functions or serverless infrastructure.
No preview deployments per PR, no built-in analytics, no automatic cache invalidation.
Tailwind CSS v4
Utility-first CSS eliminates the naming problem and keeps styles co-located with markup. v4's CSS-native configuration removes the need for a JS config file entirely.
Long class strings in JSX. Mitigated by extracting repeated patterns into components rather than @apply directives.
Framer Motion v12
The animation API maps directly to React's mental model — animate on mount, exit on unmount, layout animations via layoutId. The page transition system uses template.tsx + motion.div for fade-in on navigation.
Bundle size (~30KB gzipped). Acceptable for a portfolio site where polish is the point.
react-force-graph-2d
Canvas-based graph rendering handles the knowledge graph's 26+ nodes smoothly. The library supports custom node painting, which lets me color-code by type and scale by connection count.
Requires ssr: false dynamic import (Canvas doesn't exist during SSR). The graph is client-rendered, not part of the static HTML.
Cron-based Data Pipelines
Spotify, Flickr, and Steam data require API keys or OAuth. Instead of a server, GitHub Actions crons run fetch scripts every 30min–6h and commit JSON files to the repo. The site reads from raw.githubusercontent.com — no redeploy needed.
Data staleness up to the cron interval. Git history accumulates data commits. Both are acceptable trade-offs.
MDX over plain Markdown
MDX lets me embed React components inside blog posts — interactive code blocks, LinkedTerm hover cards, custom callouts. This is essential for a site that treats content as an interconnected graph, not isolated pages.
Slightly more complex build pipeline (next-mdx-remote + gray-matter). Worth it for the authoring flexibility.
View Transitions API for Theme Toggle
The circular reveal effect when switching dark/light mode is pure CSS — no JavaScript animation library needed. It creates a memorable micro-interaction that visitors notice and remember.
Not supported in all browsers (Firefox partial). Falls back gracefully to an instant theme switch.
Full Stack
The complete technology surface documented in one place — see /uses for the development environment.
Framework
Next.js 16 (App Router)
Styling
Tailwind CSS v4
Animation
Framer Motion v12
Graph
react-force-graph-2d
Content
MDX + gray-matter
Tooltips
Radix UI Hover Card
Icons
Lucide React
Hosting
GitHub Pages
Analytics
Umami Cloud
CI/CD
GitHub Actions