KeyDo: A CRT Arcade-Style Typing Dojo
A retro arcade-style web typing game: four training modes, martial-arts belt ranks, a global leaderboard, purely frontend and playable offline. How it's built, and the trade-offs behind a pile of technical choices.
There’s no shortage of typing tools, but most look like an exam. I wanted one that’s addictive to play — so I built KeyDo: a retro CRT arcade-style web typing dojo. Keys like a sword, mind like water; you practice, and you want one more round.
Purely frontend React + Vite, one Cloudflare Worker hosting both the static assets and the leaderboard API, fully playable offline too.
Four training modes
- Novice dojo: 11 keyboard lessons, from home row
asdf jkl;to programming symbols, with a virtual keyboard and finger hints, and accuracy ≥ 90% to unlock the next — for learning touch typing from zero; - Speed test: monkeytype-style per-character timing, with words / sentences / code as the three sources, 15 / 30 / 60 seconds, live WPM;
- Time challenge: a 60-second word sprint, space to submit, combo bonuses, difficulty climbing with level;
- Word rain: words fall from the sky, type the first letter to lock a target, finish the word to destroy it, lose a life on landing — playful real combat.
The first two share one per-character typing engine; the latter two are each their own game. Four modes, one dojo.
Ranks, to give practice a goal
Ranks are assigned by best WPM, climbing all the way from white belt to grandmaster (110+ WPM), with yellow, orange, green, blue, purple, brown, black belts between — a nod to martial-arts belts. Practice isn’t for a cold number; it’s for watching yourself climb from white belt up. Scores and lesson progress are stored locally in the browser, so you pick up where you left off.
A few technical choices
Building this little game, a few decisions are worth mentioning in hindsight:
- Not one audio file for the sound effects: hit, miss, level-up, game-over, the whole 8-bit set is synthesized live by Web Audio oscillators — 45 lines of code, zero audio assets, zero load requests;
- The game loop doesn’t go through React state: word rain steps physics at 60fps, with all state in
refs, triggering a repaint via an empty tick — otherwise asetStateper frame freezes it; - The typing engine keeps the truth in a ref: high-frequency keyboard input doesn’t go into async state; the event handler mutates a ref synchronously and commits a snapshot to render, dodging the StrictMode double-invocation trap;
- The leaderboard sets a server-side floor: scores are frontend-computed, so the backend uses a “no human can cross” cap to block the dumbest cheats, without chasing to eliminate all of it.
Each of these gets its own post later. The shared stance: don’t pull in extra dependencies where determinism will do, hold the floor where defense is needed, but don’t over-engineer a typing game either.
Offline-first, leaderboard optional
The game itself doesn’t depend on the network: word lists, lessons, scoring, saves are all local, and it plays fine offline. The global leaderboard is an optional bonus — speed test, time challenge, and word rain auto-submit your best score at the end, and the first open hands you an anonymous dojo name (like “Candle-Bearing Warrior #D2B5”), no signup. Get on the board if you want, and staying offline doesn’t stop you from practicing. The stats page also has WPM trends, the last 14 days’ activity, and per-mode summaries, so your progress is visible.
Takeaways
KeyDo aims at something simple: turn the tedium of “typing practice” into an arcade game you want to play one more round of.
- Four modes, one dojo: from zero-basis key lessons to playful word rain, covering learn, practice, play;
- Ranks for motivation: white belt to grandmaster, progress made visible;
- Purely frontend, playable offline: the core has zero network dependency, the leaderboard is optional;
- Restraint in the tech: sound effects in code not files, the game loop on refs not state, the leaderboard a floor not a heavy backend.
It’s live at typing.app.mahui.me, open and play. The next posts take apart the implementation — the typing engine, Web Audio sound effects, the word-rain game loop, and leaderboard anti-cheat — one at a time.
Comments