A clean, zero-dependency typing-speed trainer that runs entirely in the browser — built to measurably improve real words-per-minute, not just test it.
🔗 Live demo: https://ghravenlabs.github.io/WPM-Trainer/
- Case study — how the app turns a simple typing test into a training loop.
- GitHub Actions runs regression tests for saved progress and session controls, plus static app checks, on every push.
- Live test — Easy/Medium/Hard text, 15/30/60s, with net WPM, accuracy, errors updating as you type
- Per-character error highlighting + blinking caret
- Finger keyboard — color-coded by finger; the next key glows and tells you which finger to use (trains touch typing)
- Shifted punctuation hints use the displayed US QWERTY layout (for example,
?highlights/plus Shift); other physical layouts may differ. - Weak-key drills — records every key you mistype and generates a drill targeting your worst keys
- Progress tracking — best, average, streak, and a sparkline with your goal line (all saved locally)
- Export progress — download a versioned JSON snapshot of test history and weak-key counts, including session-only progress when browser storage is blocked. Export does not clear your history; importing backups is not yet supported.
- Custom text + a celebratory confetti when you beat your goal
- Honors the operating system's reduced-motion preference by disabling caret animation, transitions, and confetti.
Custom practice converts pasted line breaks, tabs, and other whitespace runs to a single ordinary space so multiline text can be typed using the spacebar. Cancelling the prompt or pasting only whitespace keeps the current session running.
Custom text is scored by Unicode code point, including characters outside the basic multilingual plane. Input still uses individual key events; IME composition and multi-code-point grapheme input are not supported.
WPM counts correct characters still present in the text, so deleting and retyping the same character cannot inflate speed. Accuracy and weak-key history retain all typing attempts, including mistakes later corrected with Backspace.
- Vanilla HTML/CSS/JavaScript — no frameworks, no build step, no dependencies
localStoragefor progress + weak-key history ·IntersectionObserver-free, pure DOM- Single self-contained file → works offline, deploys anywhere static
- Locally: open
index.htmlin any browser. - Deploy: push to GitHub and enable Pages — it's static, so it just works.
Everything runs client-side; your stats live only in your browser's localStorage.
If browser storage is blocked or full, practice continues with session-only progress and a
visible notice. That temporary progress disappears when the page closes. Invalid saved entries
are ignored so they cannot prevent the trainer from starting.
The newest 500 completed tests are retained, which bounds local-storage growth while preserving
enough history for long-term progress review.
Run node --test tests/trainer.test.cjs with Node.js 24. No package install is needed.
Ctrl/Cmd/Alt shortcuts and in-progress IME composition are ignored by scoring; ordinary
characters and AltGraph input still reach the trainer. Full IME text-entry support is not implemented.
MIT © Rolly Calma (Ghraven)
