~/projects/piano-memory-match⎇ main✓❯cat case-study.md
Piano Memory Match
A music memory game — match pairs of notes by sight or by ear, across ten instruments. Built in Svelte + Tone.js with a pure-FSM game engine and 56 unit tests.
- Solo developer
- May 2026
- shipped
Context
A small but properly-built music game: flip pairs of cards and match them by sound, across ten instruments, four difficulties, and an optional ear-training mode where labels are hidden and you match by listening alone. The point wasn’t novelty — it was building something small to the bar of every interaction is tested and every edge case is handled.
What I built
- Designed the game logic as a pure finite state machine (
idle → firstFlipped → secondFlipped → resolving → won) — unit-testable, no race conditions, easy to reason about. - Built the audio layer on a single Tone.js
AudioContextsingleton — piano usesTone.Samplerover real mp3 samples (pitch-shifted to fill chromatic notes); the rest are synthesized, so no extra sample files are required. - Added an “Match by Ear” mode — cards stay face-down even when flipped; pairs are identified by sound alone.
- Free-Play virtual keyboard, four difficulty curves (4 / 8 / 12 / 16 pairs, Expert spans two chromatic octaves), star ratings with per-instrument personal bests, waveform viz synced to master output, confetti on win.
- Keyboard nav (Tab/Space/R/Esc),
prefers-reduced-motion-aware 3D flip, mobile-friendly with ≥44px touch targets. - 56 unit tests in Vitest covering the engine, seeded shuffle, scoring, and storage.
Stack
Svelte 4 · TypeScript · Vite 5 · Tone.js 15 · canvas-confetti · Vitest
Outcome
Live at piano.iant.my.id. Small surface area, but every screen, transition, and audio path has a deliberate decision behind it.