karteikarten-engine

Shared engine for two flashcard web apps on GitHub Pages:

Both apps load /karteikarten-engine/app.js and /karteikarten-engine/app.css, so a change here reaches both apps on the next Pages deploy.

The engine holds no personal data or settings: no texts, word lists, progress, colours or keys. Everything that belongs to one person lives in that person’s app repo.

What is here

What stays in each app

index.html (window.APP: repo, storage key, all UI texts in t, card fields (with en the cards carry an English meaning next to the Arabic one, shown by the “Bedeutung zeigen” option; with syn one or two German synonyms as chips; with forms the other parts of speech of the word on the same card, one of which the learn card shows at random; a one-time button under Daten fills all of that in for old cards and merges families with several cards into one), Gemini rules including intro and end, reminder texts in remind, push key vapid, speaking prompts in practice, and optionally phrases (fields, Gemini rules, starter-set prompt, new phrases per day); colours, fonts, icon), cards.js, manifest.json, sw.js (browsers require it in the app’s own folder), the reminder workflow, and the progress on the app’s progress branch.

Phrases

With window.APP.phrases set, the phrases (openers, fillers, set phrases) get their own tab next to the words (data-mode="phrases" in the app’s nav). Phrases are ordinary entries in cards.js with "k":"p" and "g":"x", grouped by cat (what they are for). They are reviewed in the learning tab with their own daily limit for new ones (newDay.p in the progress), are left out of the article quiz, word families and practice words, and the + in speaking practice saves to them. Without phrases the app behaves as before.

Working on the engine

npm install
npm run build     # src/ → app.js (commit app.js and app.js.map together with src/)
npm test          # build check, unit tests, browser suite

CI runs the same on every push; a push whose app.js is not the build of src/ fails the check.

Adding a view: create src/ui/views/<name>.js exporting create<Name>View(ctx) → { mode, render, actions, change?, input?, keys?, enter?, after?, sayCard? }, register it in main.js, add the tab button to each app’s index.html (the dock picks it up by its data-mode). Actions are keyed by data-act; they receive the clicked element. Everything derived from the card list (families, topics, lookups) comes from ctx.store, which rebuilds its indexes after push, remove and syncWith.

The browser suite needs both apps checked out next to this repo (or AMR_DIR / EMAN_DIR):

The word lists are read from fixed commits of the two app repos (PIN in the test), so both checkouts need that history. For de-karteikarten the test compares against a SHA-256 of what its original engine produced (tests/fixtures/amr-expected.sha256). tests/fixtures/sample-progress.json is made-up data.