Open-source practice-app engine

The mill that grinds questions into knowledge.

Bring a folder of JSON — a learning pack — and quizmill turns it into a fast, installable, offline-first practice app. Better still: don't write the questions at all. Your AI agent does.

« three commands to your own practice app »
npx quizmill new my-topic
npx quizmill run my-topic
npx quizmill build my-topic
Solar System Practice — the bundled demo pack, live

↑ This isn't a video. Get one wrong — watch it come back.

One engine, endless apps

Every pack becomes its own app.

Title, icon, theme, categories — all generated from the pack manifest at build time. Pick a pack, then actually use the app: practise, unlock a sticker, check your progress. It's all in there.

⊕ Add to Home Screen — works offline

Not just flashcards

A practice app that keeps you coming back.

Stickers to chase, progress to watch climb, and explanations that actually teach — every pack ships the lot. Here's a real look.

★ Sticker cabinet

Streaks, volume, daily habit, per-category mastery.

🔥Hot streak
💯Centurion
🪐Planets
🗓️A whole week
🚀Legendary
Flawless

▥ Progress

🔥 6-day streak

Accuracy by category, and the trend over time.

Agentic Architecture81%
Claude Code86%
Tools & MCP61%

Last 7 days — weak spots re-queue for review.

✎ Explanations that teach

Markdown, with real source links and attribution.

Correct.

Endpoints are computed from the Service selector — no matching Pod labels means an empty endpoint set. DNS still resolves; it just points at nothing. Kubernetes docs: Service ↗

Source: kubernetes.io · reviewed

The authoring story

You don't write packs. Your agent does.

quizmill ships a create-learning-pack skill. Open the repo in Claude Code (or any agent that reads project skills), say what you want to learn, and the agent scopes it, writes the bank, and loops on the validator until the pack is clean. Malformed content can't reach the app.

claude — ~/quizmill
1 The skill scopes topic, level & categories with you
2 The agent writes the pack — manifest, questions, scenarios
3 The validator is the contract — it loops until clean
4 Activate, run, practice — your app is live

Grist for the mill

A pack is three JSON files. That's the whole format.

{
  "schemaVersion": 1,
  "id": "k8s-networking",
  "title": "Kubernetes Networking",
  "description": "Services, Ingress, DNS and NetworkPolicy, drilled.",
  "homeSubtitle": "Packets find a way.",
  "themeColor": "#7c3aed",
  "categories": [
    { "key": "services", "label": "Services & kube-proxy", "weight": 0.4 },
    { "key": "ingress",  "label": "Ingress & Gateway",     "weight": 0.3 },
    { "key": "netpol",   "label": "NetworkPolicy",         "weight": 0.3 }
  ]
}
[
  {
    "id": "k8s-networking-services-001",
    "categoryKey": "services",
    "difficulty": 3,
    "prompt": "A ClusterIP Service routes to zero endpoints. What's the most likely cause?",
    "options": [
      { "key": "A", "text": "kube-proxy is not running on the control plane" },
      { "key": "B", "text": "The Service selector doesn't match any Pod labels" },
      { "key": "C", "text": "CoreDNS has no record for the Service" },
      { "key": "D", "text": "The Pods lack a readinessProbe" }
    ],
    "correctKey": "B",
    "explanation": "Endpoints are computed from the selector; no matching labels → empty endpoint set. DNS still resolves (C) — it just points at nothing.",
    "source": "generated",
    "reviewStatus": "reviewed"
  }
]
[
  {
    "id": "checkout-outage",
    "title": "The checkout outage",
    "stem": "It's 09:02 on Black Friday. Checkout pods are healthy but the Service returns connection refused for ~20% of requests..."
  }
]

Schema v2 adds the rest — 2–6 options (true/false through multi-choice), images on questions and answers (non-verbal reasoning included), an optional concepts.json of teaching cards shown after a wrong answer, and a pack-defined level dimension to filter practice by. v1 packs keep working unchanged.

The Zod schema + validator CLI (npx quizmill validate) cross-checks ids, category references, scenario references and weights — and exits non-zero with per-question errors. That's what agents loop on.

The full breadth

Everything ships in every pack.

⟳ Mistakes that come back

Wrong answers queue up and are re-asked until you rescue them. The loop is the product.

◌ Unseen-biased practice

Weighted random selection that favours questions you haven't met, tunable per category blueprint.

🖼 Images & any question shape

Questions and answers can carry images — non-verbal reasoning, diagrams — and options run 2–6, from true/false to multi-choice.

📖 Concept cards & levels

Short teaching cards surface after a wrong answer, and pack-defined level bands (Year, grade, CEFR…) let you filter practice.

▦ Offline-first PWA

Installable to the home screen with a versioned service worker. Aeroplane-mode proof.

★ Sticker cabinet

Streaks, volume, daily habit, and per-category mastery — every pack grows its own cabinet of earned stickers.

▥ Progress charts

Accuracy by category and over time, plus a weakest-questions list that links straight back into practice.

✎ Per-question feedback

Thumbs up/down with comments, surfaced in Settings so pack authors can curate the bank.

↗ Source attribution

Questions carry a sourceRef; the answer panel links to the original author's work.

⇅ Optional cloud sync

Magic-link auth + Supabase mirroring with a retry queue. Dormant unless you configure it.

⌂ Private by default

Packs are gitignored and never enter the engine's history. Private GitHub repos install fine.

▲ Deploy anywhere

npx quizmill build emits a plain static site — Cloudflare Pages, GitHub Pages, Netlify, a USB stick.

Take it home

Install it your way.

Scaffold a pack

npx quizmill new my-topic
npx quizmill run my-topic

No clone, no install — npx fetches the engine for you. Edit the JSON (or hand it to your agent), then run.

Install a published pack

npx quizmill list
npx quizmill run quizmill/pack-claude-cert

Any GitHub repo with a valid pack works — private ones too, through your own git clone access.

Publish your own

# pack.json + questions.json in a repo
npx quizmill validate my-topic
git push   # → installable by anyone

PR it into the registry and it shows up in quizmill list.