dfejza.com
All builds
Web

Piano App (name TBD)

WIP· pre-alpha

Four piano skill games designed to make daily practice addictive. Follows the 'Typing of the Dead' model — piano skills are the core game mechanics, not a layer on top. Visual note reading, finger independence drills, bass pattern rhythm, and chord QTEs, all collecting granular performance data to surface weak spots and track progress over time.

TypeScriptReactVitePixiJSVexFlow

AI-generated: this write-up was drafted by AI from the project's source code and may contain inaccuracies.

A work-in-progress practice tool: four piano skill games that try to make daily practice habit-forming by making the skill itself the game. The model is borrowed from Typing of the Dead — you don't play a game that happens to involve piano, you play piano and that is the game. Four mechanics are planned: visual note reading, finger-independence drills, bass-pattern rhythm, and chord QTEs. Each session writes granular performance data to a versioned localStorage schema, with the longer-term aim of surfacing weak spots and tracking progress over time. It is pre-alpha and built mostly to learn the rendering and timing stack rather than to ship a finished app.

Architecture

A single-page app on Vite + React 19. The browser is doing three things at once per game: rendering music notation, playing sampled audio, and running a real-time game loop — so each game is essentially an input source feeding a scoring layer that persists to local storage.

flowchart TD
    accTitle: Piano practice app per-game data flow
    accDescr: Keyboard or pointer input drives a React and PixiJS game loop. The loop uses VexFlow for notation and smplr for piano samples; both feed a scoring layer that persists per-session metrics to versioned localStorage.
    IN["keyboard / pointer input"]
    LOOP["game loop (React + PixiJS)<br/>per-game mechanic<br/>note read / drill / rhythm / chord QTE"]
    VF["VexFlow 5<br/>notation"]
    SM["smplr<br/>piano samples"]
    SCORE["scoring<br/>per-session metrics"]
    LS[("localStorage<br/>versioned schema")]
    IN --> LOOP
    LOOP --> VF
    LOOP --> SM
    VF --> SCORE
    SM --> SCORE
    SCORE --> LS

VexFlow 5 renders notation in real time as the prompt changes. smplr handles piano sample playback so a played or expected note can be heard. The space-themed game is rendered with PixiJS 8 rather than DOM, since that mechanic needs a frame-by-frame canvas loop instead of React re-renders.

The four games

The point of splitting into four games is that each one isolates a different skill, so the collected data can attribute a weakness to a specific dimension rather than to "piano" in general:

  • Visual note reading — read notation and respond, scored on accuracy and latency.
  • Finger-independence drills — patterns that force independent finger control.
  • Bass-pattern rhythm — timing against a repeating bass line.
  • Chord QTEs — quick-time chord prompts.

Mechanics, scoring weights, and the localStorage schema are still in flux; the schema is versioned precisely because it is expected to change while the games are being designed. There is no backend — everything runs client-side and persists locally.