I'm building Hantu as a focused Chinese-learning MVP rather than a general flashcard app. A learner plans batches of characters, sees a full learning card with readings, meanings, example sentences, audio, components, and stroke order, then has to retrieve the character, pinyin, meanings, and a drawn version from memory. The trainer grades those parts separately, so a mostly correct answer is not flattened into a single pass/fail result.
The app is a static Astro site with TypeScript doing the interactive work in the browser. There is no application server or account system in the current version. Character data is shipped as static JSON, stroke paths are fetched per character, and learner state lives in IndexedDB. Attempts, character progression, sessions, schedules, explanations, and card-share events are stored independently; the settings screen can export and import a backup. This keeps the deployed app simple while making the learning record detailed enough for later analysis.
The study model is deliberately explicit. A configurable acquisition ladder places reviews from immediate recall through the first few days, while the scheduler uses review windows and deterministic priorities instead of silently shifting a target because a session was late. Learning and review sessions are distinct from manual practice, and teaching a character to someone else is recorded as an append-only explanation event rather than treated as evidence that the character was retained. The verification screen also supports replaying or overlaying the learner's strokes, and completed cards can be rendered for sharing.
The other half of the repository is the data pipeline under scripts/. It vendors pinned HSK source files and Make Me a Hanzi data, builds a deterministic corpus, generates per-character dictionary entries where judgment is needed, synthesizes audio, validates the results, and publishes the static assets consumed by the MVP. The split is intentional: syllabus levels, stroke counts, readings, radicals, and compounds should come from source data where possible, while the model is used for explanations and translations. Per-character files make generation resumable and rejected entries recoverable.
The current state is a working, actively changing MVP with core unit tests, an Astro production build, and browser tests for the more fragile session-sharing behavior. It is deployed as a static build behind Caddy and Cloudflare. What remains is mostly product hardening: broader browser/CI coverage, better validation of generated language quality, and more iteration on the drawing experience—especially the limits of using a mouse or trackpad for handwriting. There is no analytics or external uptime monitoring yet, so real usage will determine which parts deserve the next round of work.