Client-Side Web Application

Kemotype

Hassan Firouzi
AuthorHassan Firouzi
PublishedSeptember 17, 2026
Length6 min read
Kemotype
System_Notice

Executive Summary

Kemotype is a Next.js and TypeScript typing speed test and guided touch-typing tutor that runs entirely client-side — no backend, no database. Every WPM history, key-mastery score, and streak lives in the browser, and the whole thing installs as an offline-capable PWA.

The Problem Space

Before writing any UI, I identified what actually breaks in typing-practice tools once they leave the novelty stage:

  • One-Size Drills Don't Adapt: Most typing tutors repeat the same generic lessons regardless of which keys you're actually weak on.
  • Raw WPM Hides the Real Skill: A single speed number says nothing about which specific key pairs are slow or error-prone.
  • Progress That Doesn't Persist: A typing test with no history, streaks, or mastery tracking gives you no reason to come back tomorrow.

System Architecture

Kemotype is a Next.js 16 and TypeScript app that renders and runs entirely client-side — there's no API route, no database, and no server-held state. Every test result, per-key mastery score, and theme preference is read from and written to localStorage, versioned so the schema can evolve without wiping existing progress.

  • Zero Backend, Zero Latency: All four test modes and the entire touch-typing curriculum run in-browser, so there's nothing to wait on and nothing to go down.
  • LocalStorage as the Source of Truth: History, per-key mastery, streaks, and settings all persist client-side across sessions.
  • Installable PWA: A service worker and manifest let the whole app — English and Turkish word banks and keyboard layouts included — run fully offline once installed.

Technical Implementation

The core of the touch-typing tutor is a per-key mastery tracker built on the SM-2 spaced-repetition algorithm — the same scheduling model used by tools like Anki. Every attempt on a key pair updates an ease factor and a due date, so keys you're actually struggling with resurface automatically instead of being drilled on a fixed schedule:

Terminal
export function reviewKey(card: KeyCard, quality: 0 | 1 | 2 | 3 | 4 | 5): KeyCard {
  const { repetitions, easeFactor, intervalDays } = card;

  // A poor attempt resets progress on this key — back to daily review.
  if (quality < 3) {
    return { ...card, repetitions: 0, intervalDays: 1, dueAt: addDays(Date.now(), 1) };
  }

  const nextEase = Math.max(
    1.3,
    easeFactor + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02)),
  );
  const nextInterval =
    repetitions === 0 ? 1 : repetitions === 1 ? 6 : Math.round(intervalDays * nextEase);

  return {
    ...card,
    repetitions: repetitions + 1,
    easeFactor: nextEase,
    intervalDays: nextInterval,
    dueAt: addDays(Date.now(), nextInterval),
  };
}

Key Features

  • Four Test Modes: Time, Words, Quote, and untimed Zen, all with live WPM and accuracy while typing.
  • Guided Touch-Typing Curriculum: 17 key-pairs taught in order, each through a 12-stage drill-and-words cycle.
  • Per-Key Spaced Repetition: An SM-2 scheduler resurfaces exactly the keys that need practice instead of drilling everything equally.
  • Offline-First PWA: Installable with English and Turkish word banks and keyboard layouts baked in, so it works with no connection.

Impact & Results

  • Shipped a real product I use daily to practice typing, not just a portfolio piece.
  • Deepened experience with localStorage-driven state and offline-first PWA patterns, with no backend to fall back on.
  • Built a reusable spaced-repetition scheduling module applicable well beyond typing practice.
Return to index
Authenticated EntrySeptember 17, 2026

End of Journal Entry