Skip to content

Repository files navigation

Homerow

An offline-first typing trainer that scores technique, not speed.

Most typing tests reward you for going fast however you like. This one is built around a narrower question: are your hands actually anchored on the home row, or are you floating above the keyboard and getting away with it? A fast typist with floating hands is precisely the case this is meant to catch.

Green-phosphor CRT aesthetic, no server, works offline.

Try it out here: https://vincemaina.github.io/touch-type-pro/

Running it

npm install
npm run dev

The site is two pages: a static landing page at / explaining what this is and who it's for, and the app itself at /app/.

Pick an exercise and go. Fingers shows which finger owns which key and lets you drill them one at a time — the place to start if the assignment isn't automatic yet. History tracks whether it's improving.

Technique explains what to actually aim for — whether your fingers really need to stay on the home row, how much your hands should move, and which of the usual rules are worth following versus which you can bend.

Everything is reachable from the keyboard, and every control shows its key: digits arm an exercise, home-row letters (a s d f g h j k ;) arm a variant, space starts it, esc backs out, and t c p e n toggle the technique guide, finger chart, history, CRT effects and anchor checks. You should never need the mouse, which is rather the point.

Picking an exercise only arms it — nothing starts until you press space, and space is the same key whether that's your first run or your tenth. So you can browse the variants, read what each one drills, and begin when you're ready rather than being dropped straight into typing.

Anchor checks appear as a marker in the line ahead of you, so you can see one coming and settle your hands rather than being ambushed mid-word. The marker sits between words as a word of its own — you finish the word, hit space as normal, and then anchor. If you'd rather drill without them, n turns them off — the technique score then falls back to the fingering analysis alone and says so.

Note that the hjkl exercises can only report on your anchoring, not your fingering: hjkl is entirely right-handed, so it produces no hand-alternating pairs for the timing analysis to compare against. The app says unknown rather than guessing.

How it judges technique

A keyboard event cannot tell you which finger pressed a key. Homerow works around that with two signals that need no extra hardware:

Anchor checks. Mid-drill, the screen interrupts and demands a simultaneous F + J. If both index fingers are resting on their nibs, the two keys land together. If your hands are floating, each one has to find its key independently, and they arrive measurably apart. The skew between the two keydowns is a direct read on whether your hands were home at that moment.

Timing forensics. A canonical touch typist pays a real penalty on same-finger bigrams — pairs like ed or ju where one finger has to leave a key, travel, and land again. Hand-alternating pairs like ur have no such constraint. Someone striking each key with whichever finger is nearest doesn't pay that penalty, because ed gets two different fingers. So a flat latency profile across the two classes is evidence of non-standard fingering, inferred without ever seeing your hands.

The sfb-rich drill tier exists to feed this second signal: it's deliberately dense in same-finger pairs so the analysis reaches usable confidence quickly. Those lines are meant to feel awkward — the awkwardness is the measurement.

On trusting the numbers

These are inferences, not measurements, and the app reports a confidence alongside every verdict. The thresholds are first-pass estimates from the keyboard-layout literature and want calibrating against real data. A "suspect" verdict means the expected timing signature is absent, which is evidence of non-standard fingering, not proof of it.

Once you have a few weeks of history, your own sessions are better calibration than anything preset. The constants live in src/technique/CANONICAL_RATIO and SUSPECT_RATIO in bigrams.ts, DEFAULT_THRESHOLDS in anchorCheck.ts — and each has a boundary test pinning its behaviour, so changing one is a deliberate act.

Assumes a US QWERTY keyboard

Finger assignment is keyed on physical key positions, so it holds for any layout on a standard staggered board. Two things do assume US QWERTY: the character-to-key mapping behind the finger hint in sentence typing, and the drill corpus itself. On Dvorak or AZERTY the hints will be wrong.

The exercises

  • Sentence typing across four tiers — home-row only, same-finger, natural prose, and Vim motion vocabulary — 78 lines, rotating so you walk a whole tier before any line comes round again. Names the finger that owns the next character, because knowing which finger is the part a floating-hands typist never had to learn.
  • Finger drills — one finger at a time. Every key that finger owns, with a return to its resting key between each reach, because drilling r t v b in a row teaches the reaches but not the habit that matters: coming back. A keyboard chart shows the assignment while you drill, and clicking a finger on the chart starts its drill. Every finger rotates through all eight, a different one each run.
  • Reaction drills — one key named at a time, measuring how long your hand took to find it. The return to home variant makes you put the finger back on its resting key before offering the next target; it is the most direct training here for the specific habit this app was built around.
  • A vim maze navigated with hjkl, in three sizes, the largest accepting count prefixes (3j moves three cells down). Scored on route efficiency against the shortest path, not on speed.
  • Snake, steered with hjkl on a clock that keeps running whether you do or not. Fast enough that hunting for keys will kill you.

Tracking progress

Finished sessions are kept in IndexedDB — raw keystrokes, not summaries — and the history screen recomputes everything from them: technique and anchor trends per session, a fingering verdict pooled across every stroke you have ever typed (which reaches confidence a single session cannot), and a keyboard heatmap showing which keys you are slowest to reach.

Storing raw strokes is what makes that work retroactively: a metric added later still applies to every session recorded before it existed.

Back it up. History lives in IndexedDB, which belongs to one browser on one machine and disappears whenever site data is cleared. Since the value here is cumulative — the fingering verdict only reaches confidence after many sessions — Export on the history screen writes a dated JSON file, and Import merges one back in. Import validates every record and tells you how many it could not read, rather than quietly poisoning your averages.

Also here: installable PWA, fully precached for offline use, and a CRT effect layer with three intensity levels that honours prefers-reduced-motion.

Development

npm test          # unit + integration (vitest)
npm run test:e2e  # browser tests (playwright)
npm run lint
npm run build

CI runs all of the above on every push, and main deploys to GitHub Pages. The deploy passes SITE_URL so the landing page emits an absolute canonical link; local builds omit it rather than hardcode the wrong origin. Playwright is the only check that verifies the app against a real browser — notably that a genuine keydown carries code: 'KeyF' rather than only key: 'f', which the entire finger map depends on and which jsdom cannot establish.

Architecture notes and the invariants worth knowing before editing are in CLAUDE.md; the original brief is in PROMPT.md.

The app is called Homerow; the repository is named touch-type-pro. The app name is load-bearing — it is in the manifest, the PWA identity, and the homerow: localStorage keys — so renaming it would orphan existing users' settings. The repository name is free to change if you want them to match.

License

MIT — see LICENSE.

Releases

Packages

Contributors

Languages