Tempo Typing — product requirements
Tempo Typing is a minimalist, keyboard-first typing test. People type against time, a word count, a quote or custom text, see an honest scoring breakdown, and — when signed in — keep a history, personal bests, a streak and a place on weekly and all-time leaderboards protected by server-side anti-cheat.
Problem. A typing score is only worth sharing if it cannot be faked and is computed consistently; every figure on the result screen and on a leaderboard must follow from what was actually typed.
Users
- Practising typist — A distraction-free test with accurate wpm, raw and accuracy, and control over difficulty and confidence rules.
- Competitor — Personal bests and leaderboards that only contain legitimate results.
- Guest — Try the test without an account and keep results on the device.
Goals
- Scoring follows one formula everywhere: the UI, the saved result and the API agree.
- Difficulty, confidence and paste rules are enforced as documented.
- Only valid, long-enough, non-zen, non-failed results are saved and ranked.
Out of scope
- Sign-up and password reset
- Sound output quality
- Exact wpm of human-typed runs
Contents
Typing engine and scoring
How keystrokes become a result.
- Typing "The quick brown fox jumps over the lazy dog" exactly ends the test as the final "g" is typed
- Result shows acc 100%, characters 35/0/0/0 (correct/incorrect/extra/missed), test type "custom english", and wpm equal to raw
- A guest sees "Saved on this device. Sign in to keep your history."
- Typing "Thx quickk brown fox jumps over the lazy dog" gives characters 34/1/1/0 and acc 91% (title "90.91% (40 correct / 44 keypresses)")
- wpm = (correct letters + correct spaces) / 5 per minute; raw = (all typed letters + spaces) / 5 per minute; acc = correct keypresses / total keypresses
- Toast "Pasting is disabled"; no letters are coloured
- After "Thx", space, Backspace twice and "e" the first word reads correct
- A correct previous word cannot be re-opened
- The wrong keypress still counts against accuracy (below 100%)
- After a run with errors in "The" and "quick" the practice test is exactly "The quick"
- Save line "Practice tests are not saved"
Difficulty and confidence
Rules that make a test stricter.
- Typing "Thx" does not fail yet; pressing space shows "test failed" and "Expert: an incorrect word was submitted"
- Save line "Failed tests are not saved"
- Typing "Tx" shows "test failed" and "Master: an incorrect key was pressed"
- A "confidence on" badge is shown; "Thx", space, Backspace changes nothing
- "qa" then Backspace leaves "q"
- A "confidence max" badge is shown; after "Thx", Backspace and Ctrl+Backspace leave "Thx" with the x still incorrect
Modes and configuration
Time, words, quote, zen and custom tests.
- Time 15 shows the timer 15 → 1, then a result with time 15s and test type "time 15 english"
- Hint "start typing — shift + enter to finish"
- Save line "Zen results are not saved"
- Toast "No quotes available for spanish — showing english quotes"
- Test type "quote short english" and a "source" stat
- 0 and 3601 show "Enter a whole number between 1 and 3600"
- 45 closes the dialog and the button reads "45"
- Empty text: "Text cannot be empty"
- Word limit 0: "Word limit must be 1–1000 words"
- "a b c" with word limit 7 shows "a b c a b c a"
Command line, themes and settings
Keyboard control and personalisation.
- "thmemb" highlights "Theme: ember" and previews its colours
- Esc restores the previous colours; "theme ember" + Enter keeps ember and settings shows it selected
- Hints read "esc restart test" and "ctrl + shift + p command line"
- A fresh tab shows the carbon theme (dark grey, yellow accent); after sign-in the seeded account’s lagoon theme (teal) is applied and highlighted in settings
Accounts and sign-in
Sign-in with email or username.
- Wrong password: an error alert and the sign-in page stays
- Empty fields: "Enter your email or username and password"
- Correct credentials open the account page
- Heading "guest" and one row in "local result history"; after clearing "No results yet."
Account profile and history
Stats, personal bests and result history.
- Seeded account: "joined 14 Feb 2026", tests started 41, tests completed 12, time typing 00:07:12, current streak 3 days
- time: 15 s 93 (98%), 30 s 88, 60 s 84, 120 s 76; tooltip on 15 s starts "92.80 wpm · 94.40 raw · 98.31% acc"
- words: 10 → 89, 25 → 91, 50 → 83, 100 → "-"
- "10 of 12"; first row words 10 at 89.19 wpm; "load more" shows 12 rows, the last being custom at 63.82 wpm
- Filter "quote": one row, 77.14 wpm "quote medium"
- Filter "words": three rows (89.19, 90.70, 83.13) each with ♛
- A new account’s first time 15 test shows "♛ New personal best!"
- Account page then shows tests completed 1 and the 15-second PB equal to that wpm
- Nine words typed in under 15 seconds: "Test too short — result not saved"; history total stays 12
Leaderboards
All-time and weekly rankings for time 15 and time 60.
- Time 15: top entry 148.20 wpm; the signed-in account is #8 with 92.80 ("Your rank: #8"), above an 88.04 entry
- A barred account’s 152 wpm result is not listed
- Time 60: top entry 126.30; the signed-in account #5 with 83.80
- Time 15 weekly: top entry 139.65; the 21-day-old 148.20 and the other all-time leader are gone; signed-in account #5 (92.80)
- Time 60 weekly: top entry 121.75; signed-in account #3 with 77.20 because its 83.80 best is 9 days old
Results and settings API
Server-side re-scoring and validation.
- The documented example body returns 201 with result.wpm 134.4
- wpm altered to 180: 400 "Result failed anti-cheat validation"
- testDuration 30 for time 15: 400 "Test duration does not match the selected time"
- mode "zen": 400 "Zen results are never saved"
- GET /api/typing/leaderboards/30: 404 "Leaderboards exist for time 15 and time 60 only"
- {"theme":"neon"}: 400 Invalid value for "theme"
- {"fontSize":3}: 400 Unknown setting "fontSize"
- {"theme":"ember"} is returned by the next GET
Non-functional requirements
Glossary and rules
| wpm | Net words per minute: (correct letters + correct spaces) / 5 per minute. |
|---|---|
| raw | Words per minute counting every typed letter and space, right or wrong. |
| PB | Personal best, tracked per exact configuration (mode, length, language, modifiers). |
| Confidence mode | Setting that limits correcting earlier input: off, on (space is final) or max (no backspace). |