WordScramble
A drag-and-drop spelling game for early readers. Flask, SQLite, and Alpine — no build step — with server-side scoring and adaptive practice.
My kid needed spelling practice and the games I found either drilled a fixed list or turned into an ad delivery mechanism. WordScramble scrambles letter tiles, tracks which words cause trouble, and quietly resurfaces those in dedicated challenge rounds.
The rule I held to is that the client never sees the answer. The API returns scrambled letters, the word length, and the first letter — never the solution — so the score can't be forged from the browser console. All the scoring lives in one module; an earlier version had rules scattered around and the summary page and the history page would disagree about how many points a round was worth. Routes validate input and hand off to a game layer that has no idea HTTP exists, which makes the logic straightforward to test — there are 124 tests, including directory-traversal attempts on the word-list upload.
SQLite was a deliberate pick. One child writes maybe 300 rows a week; that's not a database problem, and running Postgres for it would be all overhead and no benefit.
Next time I'd start with the challenge-word logic instead of adding it later — retrofitting the "which words are hard" tracking touched more of the schema than it should have.