2026
Personal Portfolio
Personal project
The site you're reading: a fullstack Next.js 16 app whose public surface is fully static and edge-cached, with the database-backed pieces quarantined to two server routes. A Zod-validated contact API writes to MongoDB, a from-scratch HMAC-signed admin dashboard reviews the messages, and an ambient black hole rendered in hand-written 2D Canvas is the one indulgence.
Tech stack
TypeScriptNext.jsReactMongoDBMongooseZodTailwind CSSVercelCanvas
Highlights
- Deliberate render split on the Next.js 16 App Router: Home, Journey, and Projects prerender at build time and each case study is statically generated, so only the contact API and the /admin dashboard run server-side. The static surface is edge-cached on Vercel, which auto-deploys from main.
- Contact API (POST /api/contact, Node runtime) validates with Zod and returns distinct status codes for bad input, unconfigured storage, and write failures. A honeypot field silently drops bots while still returning success, and real errors stay in the server logs while the client sees only generic messages.
- Data layer on MongoDB Atlas via Mongoose: schema-level validation mirroring the API, an indexed read flag, and timestamps. The connection is a cached global singleton with buffering disabled, so serverless invocations reuse one pooled connection and queries fail fast instead of hanging when the database is unreachable.
- Authentication built from crypto primitives, no library: a stateless HMAC-SHA256 signed session cookie (httpOnly, secure, sameSite) verified in constant time with a 7-day expiry. The admin dashboard uses React Server Actions that re-check the session before every mutation (mark-read, delete, logout).
- Front end is a sage-and-oxblood design-token system with per-route fade transitions and a full reduced-motion switch. The flourish: an ambient black hole hand-written in 2D Canvas with no animation library, a requestAnimationFrame loop, edge-aware drift, and text that brightens as the hole passes beneath it.