← Back to home@akshayDev17

quiz-app

Invite-only, timed, multiple-choice quizzes. Python Cloudflare Worker + D1, Next.js static export, Cloudflare Access (OTP).

Stars
0
Language
Python
Created
Oct 23, 2026
Updated
Oct 25, 2026

Introduction

The Quiz Room

The Quiz Room

live CI

Invite-only, timed, multiple-choice quizzes. Questions live in sets under topics; a question has any number of options and any number of them may be correct; a set can carry a time limit. Nothing is marked — no right, no wrong, no count — until the solver submits or the clock runs out.

Take a quiz | Authoring plugin | Design | Deploy | Stack

What it is

  • Sets under topics. "RAG › Embeddings and vector space · Set 1" is derived from the set's topic, subtopic, difficulty and sequence — never typed by hand.
  • Multi-correct by design. Tick any combination; the answer key is the set of options marked correct, and scoring is per set (all_or_nothing or partial).
  • The server owns the clock. The deadline is fixed at start, the browser's countdown only displays it, and closing the tab cannot buy time.
  • Pausing freezes the clock. A paused attempt keeps its time, its answers, and the exact paper it was served.
  • History is the solver's, not the author's. Editing or deleting a quiz never rewrites someone's past attempt: every attempt keeps its own copy of the questions, so the per-question breakdown survives even after the quiz is gone.
  • Invite-only. Cloudflare Access with an email one-time PIN is the only way in.

The authoring plugin → tools/

Quizzes are authored and uploaded by a packaged agent plugin, not by hand-editing JSON. It lives in this repo at tools/ and gives two skills:

SkillWhat it does
quiz-createWrites a quiz-set JSON in the house style and validates it against the server's own rules.
quiz-uploadLogs in, imports the set, publishes it — hands-off.
# Claude Code
claude plugin marketplace add akshayDev17/quiz-app
claude plugin install quiz-tools@quiz-app --scope user

# DSH
dsh plugin --profile web add file:"$PWD/tools"

Full instructions — first-run Gmail setup, usage, troubleshooting, what it leaves on disk — are in tools/README.md.

Repo layout

PathWhat
backend/Python Cloudflare Worker: the API, D1 repositories, migrations, tests.
frontend/Next.js static export: the quiz UI, deployed as static assets under /quiz.
tools/The authoring plugin — quiz-create and quiz-upload, packaged for Claude Code and DSH.
docs/design.mdThe design: topology, auth, schema, request flows.
docs/deploy.mdThe deploy runbook: Access, D1, secrets, CI, first-deploy checks.
design/Clickable frontend sketches — open the HTML in a browser.

Run it locally

Two processes; the frontend talks to the backend's origin.

# API + database, on :8787 (creates backend/quiz.db on first run)
cd backend && python3 local_server.py

# UI, on http://localhost:3000/quiz
cd frontend && npm install && NEXT_PUBLIC_API_BASE=http://127.0.0.1:8787 npx next dev

The dev server signs you in as DEV_EMAIL (default dev@example.com) and treats that address as an admin, so /admin works without Cloudflare Access.

Deploy

Per docs/deploy.md: Cloudflare Access first, then D1, then ADMIN_EMAILS. CI deploys on every push to main, so do not push to main before §A–C are complete.

Stack

The same shape as ai-chat-archive: a Python Cloudflare Worker + D1 for the API, a Next.js static export uploaded as static assets for the frontend, and Cloudflare Access (email one-time PIN) as the only way in. No framework is used in the backend — the router is a pure function of (method, path, body, identity), and every repository is the single SQL implementation that both D1 and the tests run against.