A deliberately minimal personal site: a name, a line, work and education as names and dates only, and a quiet interactive field of dots that shimmer and lean away from the cursor. No blurbs, no filler.
- Next.js 14 (App Router), exported as a fully static site
- React 18 + TypeScript
- Tailwind CSS with a small set of CSS-variable design tokens
- No UI framework, no animation library, no images. The dot field is a single
plain
<canvas>.
app/
layout.tsx Fonts, metadata, root layout
page.tsx The page (there is only one)
globals.css Design tokens + base styles
icon.svg Favicon
components/
Field.tsx The interactive dot-field canvas
lib/
content.ts Single source of truth for all content
scripts/
fix-readlink.js Node 22 / Windows build shim (see Notes)
All content (name, links, copy) lives in lib/content.ts.
npm install
npm run dev # http://localhost:3000npm run build # static export to ./outThe output in out/ is plain static files, deployable to Cloudflare Pages,
GitHub Pages, Netlify, or any static host.
- Motion respects the user. With
prefers-reduced-motion, the dot field renders a single static frame and never animates. scripts/fix-readlink.jsis a smallnode -rpreload that works around a Node 22 regression on Windows wherefs.readlinkthrowsEISDIRon regular files, which otherwise breaks the webpack build. It is a no-op on other platforms.
MIT, see LICENSE.