How This Was Built
This website is a case study in itself.
// Stack
App Router for file-based routing, React Server Components for performance, Turbopack for fast dev feedback. The gold standard for React applications.
Latest runtime with Server Components, improved streaming, and better concurrent rendering. The foundation everything else sits on.
Type safety across the entire codebase — data models, component props, MDX frontmatter. Catches bugs before they ship.
CSS-first configuration via @theme inline — no tailwind.config.ts needed. Utility-first styling with Lightning CSS under the hood for vendor prefixing.
Industry-standard animation library. Scroll-driven reveals, timeline draw animations, magnetic buttons, card tilts. Finer control than Framer Motion for scroll-linked effects.
Particle mesh on the hero section via @react-three/fiber v9 and @react-three/drei v10. GPU-accelerated, cursor-reactive, performance-conscious.
Blog posts and case studies written in Markdown with React components. Content lives in the repo — no CMS dependency. Rendered via next-mdx-remote.
For the "hire me" easter egg. Sometimes shipping means shipping confetti.
Clean, consistent icon set. Tree-shakeable — only the icons used are bundled.
// Hosting
Vercel
Zero-config Next.js deployment. Edge functions, automatic preview deployments, instant rollbacks. The deploy target Next.js was built for.
Cloudflare
DNS proxy, SSL termination, DDoS protection, and global CDN. The notjustapm.dev domain is registered and managed here.
// Design
Typography
Clash Display (Fontshare) for headings — geometric, bold, modern. Satoshi (Fontshare) for body — clean and readable. JetBrains Mono (Google Fonts) for code and technical accents. Press Start 2P for the Konami easter egg.
Theme system
Dark mode default with Electric Blue (#0066FF) and Amber (#FFB800) accents. Light mode toggle. Hidden Overdrive mode — neon cyan + magenta with CRT scanlines — activated by toggling the theme 5 times in 3 seconds.
// Animation Philosophy
“Every animation serves a purpose — to guide attention, create delight, or demonstrate craft. Nothing moves without intent.”
Five animation layers: cinematic page load, Three.js particle mesh, GSAP scroll-driven reveals, micro-interactions (magnetic buttons, card tilt, custom cursor), and easter eggs. All respect prefers-reduced-motion.
// Decisions & Trade-offs
GSAP over Framer Motion
Framer Motion is great for component-level animation. But for scroll-linked effects — timeline draws, scrub-driven reveals, stagger cascades — GSAP's ScrollTrigger gives finer, more predictable control.
Three.js over Spline
Spline is beautiful for 3D scenes but ships a heavy runtime. The particle mesh needed to be lightweight, cursor-reactive, and composable with React. Raw Three.js via @react-three/fiber gave full control at a fraction of the bundle size.
Tailwind 4 over Tailwind 3
Tailwind v4's CSS-first configuration means no tailwind.config.ts — the theme lives in globals.css via @theme inline. Lightning CSS handles vendor prefixing. Simpler, faster, fewer moving parts.
MDX over a CMS
Blog posts and case studies are .mdx files in the repo. No API calls, no auth, no vendor lock-in. Content is version-controlled alongside the code that renders it.
Formspree over custom backend
A contact form doesn't need a custom API route, database, and email service. Formspree handles validation, spam filtering, and delivery. Shipping > overengineering.
// Easter Eggs
There are 8 hidden interactions on this site. It started with 4 — then I couldn't stop. Finding them all is left as an exercise for the curious.
Hints: one involves a classic cheat code. One breaks physics. One takes you back in time. One fuels the developer. And one? You're probably already looking in the right place.