Skip to content
appsbynate
← productivity

Study

Flashcards with real spaced repetition and quizzes built from them, running entirely in the browser — no account, no server, no subscription.

Section
productivity
Year
2026
Role
Solo project
Stack
Next.js, React, TypeScript, Dexie, IndexedDB

Summary

Flashcards with real SM-2 spaced repetition, plus quizzes built from the same cards. Everything runs client-only — decks, due dates and review logs live in IndexedDB through Dexie, with a JSON backup as a first-class feature. No account, no server, no subscription.

Story

lib/ is pure logic and it’s where the thinking goes: every module takes data and returns data and has a test file beside it, and exactly one module is allowed to import the database. The scheduler never reads the clock — today is an argument — so a session crossing midnight stays consistent and the algorithm is testable without faking time. The rating buttons show the interval each one will cost before you press it, because a scheduler you can’t see is a scheduler you don’t trust. The rest was invariants that never fail loudly: a day is a YYYY-MM-DD string and an instant is epoch milliseconds; review intervals are clamped to whole days so the button label can’t promise something the schedule won’t deliver; and a card’s new state and its review log are written in one transaction, since a card without its log breaks the streak and a log without its card replays the same question forever.

Lessons

  • The invariants worth the most are the ones whose violation is invisible for weeks. They need tests, not review.
  • Validate restored data rather than casting it — half-shaped records crash a screen three clicks later, with the good data already overwritten.
  • A colour defined only inside a media query or [data-theme] block doesn’t apply in the default “system” state. That produced a 1.06:1 failure here once.