One of our kids was working on letter recognition, so I made Liberty Letters: March to Victory. It is a browser game with a friendly, Revolutionary War–themed storybook scene.

A child hears a letter and chooses it from three large tiles. Each correct answer moves Liberty Company farther across the scene. A wrong answer does not take away progress; the game asks the player to listen and try again.

I also made a printable letter-recognition activity. The PDF has letter missions that can be used away from the browser.

How the game works

The game is a from-scratch TypeScript app built with Vite. The shipped game itself has no game engine, no canvas library, and no graphics package: the board and every icon are inline SVG, styled with plain CSS, and easy to inspect in a browser’s dev tools. Vite and the project’s test tooling (Playwright, Vitest, ESLint) stay build- and test-time dependencies; none of them ship to the browser. Letters are spoken aloud through the browser’s native Web Speech API rather than a recorded voice file or an external text-to-speech service, with a preference for a local English voice when one is available.

A round is a small state machine with three phases (question, advancing, victory), so a tap that lands while the board is mid-animation is simply ignored instead of double-counting or breaking the sequence. Wrong answers increment a stumble counter but never move the child’s step backward; the code that decides correct/incorrect never has a path that decreases progress, which is what “no progress loss” actually means here rather than just a design intention. Similar-looking letters (M/N/W, b/d/p) are used as deliberate distractor choices rather than random ones. Ten correct answers finish a battle. One early fix widened the sound-mute button to meet a 64-pixel minimum touch target after it turned out too small for the device it was meant for.

The printable is a separate pipeline

The browser game and the printable PDF share the alphabet-based premise and the Revolutionary War framing, but they don’t share rendering code. The printable is generated offline: a script builds the activity as HTML, then uses Playwright’s bundled Chromium to print that HTML to a letter-size PDF. That’s the same browser automation tool used for this project’s end-to-end tests, but a separate script from the game itself. A second, related tool in the same repository generates seeded, five-map campaign PDFs from a deterministic model rather than from the game’s own letter logic, with its own verification script that renders contact-sheet PNGs of every generated map so a whole campaign can be checked at a glance instead of opening five PDFs by hand.

All artwork, in the game and in the printables, is original local SVG/CSS, not an external asset or image-generation API. That was a deliberate constraint on the project, not just how it happened to turn out: a build note in the repository states outright that only local vector marks were in scope.

A real design bake-off

The campaign-map artwork went through a genuine bake-off rather than one attempt: I built three complete, competing visual directions (an illustrated storybook style, a wooden-block wargame style, and an antique engraved-atlas style), each as its own working proof with a rendered page, a thumbnail, and a short written tradeoff summary, before picking a direction to keep.

Verification

The project’s own local check runs type-checking, linting, the unit-test suite, a production build, and the Playwright end-to-end suite in sequence before anything is considered done. Unit tests cover the letter/distractor logic, the round state machine, the mute toggle, and the campaign-map data model; the end-to-end suite includes a smoke test, a full screenshot pass, and a dedicated test for the campaign generator page. There’s no CI pipeline wired up for this repository, so these checks run locally, not on every push.

Play or print it