A game-design portfolio and CV built as a fog-of-war hex map. Personal site for Somya Soni, showcasing Echo Maze (a stealth puzzle navigated by sound) and Territory Wars (a hex-map location game built for RevenueCat Shipaton 2026).
- Next.js 15 (App Router) + TypeScript
- Tailwind CSS 3.4 — all design tokens live in
lib/tokens.tsand flow intotailwind.config.ts; no ad-hoc hex values in components - react-three-fiber + three — the hero's instanced hex grid
- Framer Motion — scroll reveals, the trajectory trail, the cursor HUD
npm install
npm run dev # http://localhost:3000
npm run build # production build
npm run lintThe hero is an instanced hex grid that starts unlit. A ping — cursor position
on desktop, scroll position on mobile — ramps nearby hexes to signal-amber
over 120ms, then decays over 600ms on cubic-bezier(0.22, 1, 0.36, 1). Lit
hexes reveal fragments of each game's mechanic diagram buried underneath.
prefers-reduced-motionswaps every reveal for an instant state change and renders the hex grid statically — no JS watches pointer or scroll in that mode- Visible focus states everywhere (2px
signal-amber, 2px offset) - Contrast holds at WCAG AA against the dark background
- The custom hex cursor only mounts on fine-pointer devices; touch keeps native behaviour
app/ routes: / and /work/[slug]
components/
hero/ hex map scene, HUD frame, copy, stat bar
projects/ hex project tiles, case-study panels
trajectory/ the CV timeline, drawn as a campaign map
about/ blended portrait + bio
skills/ contact/ layout/ ui/
lib/
tokens.ts design tokens (mirrors DESIGN.md)
content.ts all copy, typed
easing.ts bezier LUT for the per-frame ping decay
hexCoords.ts pixel → axial hex coordinates for the cursor readout
Grep CONTENT GAP — these render as visible "to be added" states rather than
invented filler:
- Degree programme and graduating year
- Role and tools per project (solo/team, engine)
- Engineering and Tools toolkit groups
- Two or three more About sentences
- GitHub / LinkedIn / itch.io links
- Project visuals (diagram and screenshot slots are reserved)
Deployed on Vercel. Pushes to main trigger a production deployment.