Skip to main content

A minimalist MCQ quiz web application

Project description

SnekQuiz ๐Ÿ

Python 3.13 Ruff ty pre-commit

A minimalist multiple-choice quiz web application built with FastAPI, HTMX, and Jinja2 templates.

[!NOTE] This project was vibe-coded with Claude Opus 4.6 ๐Ÿค–โœจ

Features

  • Role-based auth โ€“ admins and quiz-takers via HTTP Basic authentication
  • Quiz catalogue โ€“ home page lists all quizzes, highlighting completed vs new
  • Paginated questions โ€“ one question at a time with instant feedback via HTMX
  • Results page โ€“ score summary with per-question review (safe to refresh)
  • Admin portal โ€“ upload quizzes, view aggregated results, delete quizzes
  • Quiz API โ€“ POST /api/quizzes (admin), GET /api/quizzes, DELETE /api/quizzes/{id} (admin)
  • SQLite storage โ€“ lightweight, zero-config persistence via aiosqlite
  • YAML config โ€“ app settings parsed into Pydantic models, logging via dictConfig

Quick Start

# Install dependencies (requires Python 3.13+ and uv)
uv sync

# Run the app
uv run snekquiz

# or run via the CLI entry-point
snekquiz

# or via python -m
python -m snekquiz

# or via uvicorn directly
uvicorn snekquiz:create_app --factory

The server starts at http://localhost:8000. Log in with one of the default accounts configured in src/snekquiz/config/app.yaml:

Admins can also take quizzes. The admin portal is at http://localhost:8000/admin.

Uploading a Quiz

Via the admin portal at /admin/upload, or via the API:

curl -u admin:admin \
  -H "Content-Type: application/json" \
  -d @quiz.json \
  http://localhost:8000/api/quizzes

See the example quiz format below.

Example quiz.json
{
  "quiz_name": "Cities quiz",
  "questions": [
    {
      "id": 1,
      "question_type": "single_answer",
      "question_text": "What is the capital of France?",
      "options": [
        {"id": "A", "text": "Paris"},
        {"id": "B", "text": "London"},
        {"id": "C", "text": "Berlin"},
        {"id": "D", "text": "Madrid"}
      ],
      "correct_answers": ["A"],
      "explanation": "Paris is the capital and largest city of France."
    },
    {
      "id": 2,
      "question_type": "multiple_answer",
      "question_text": "Which of the following are cities in Europe?",
      "options": [
        {"id": "A", "text": "Paris"},
        {"id": "B", "text": "London"},
        {"id": "C", "text": "Singapore"},
        {"id": "D", "text": "Perth"}
      ],
      "correct_answers": ["A", "B", "D"],
      "explanation": "Paris (France), London (England), Perth (Scotland)."
    }
  ]
}

Project Structure

src/snekquiz/
โ”œโ”€โ”€ __init__.py          # App factory & CLI entry-point
โ”œโ”€โ”€ auth.py              # Authentication including LDAP layer
โ”œโ”€โ”€ database.py          # SQLite database layer (aiosqlite)
โ”œโ”€โ”€ models.py            # Pydantic models (config + quiz data)
โ”œโ”€โ”€ routes.py            # Web & API routes
โ”œโ”€โ”€ config/
โ”‚   โ”œโ”€โ”€ app.yaml         # Application settings
โ”‚   โ””โ”€โ”€ logging.yaml     # Python logging dictConfig
โ”œโ”€โ”€ templates/
โ”‚   โ”œโ”€โ”€ base.html        # Base layout
โ”‚   โ”œโ”€โ”€ home.html        # Quiz catalogue
โ”‚   โ”œโ”€โ”€ complete.html    # Quiz completion interstitial
โ”‚   โ”œโ”€โ”€ question.html    # Question page
โ”‚   โ”œโ”€โ”€ results.html     # Results / score page
โ”‚   โ”œโ”€โ”€ admin/
โ”‚   โ”‚   โ”œโ”€โ”€ dashboard.html    # Admin overview with aggregated stats
โ”‚   โ”‚   โ”œโ”€โ”€ quiz_detail.html  # Per-quiz attempt drilldown
โ”‚   โ”‚   โ””โ”€โ”€ upload.html       # Quiz upload form
โ”‚   โ””โ”€โ”€ partials/
โ”‚       โ””โ”€โ”€ answer_feedback.html   # HTMX fragment for answer feedback
โ””โ”€โ”€ static/
    โ””โ”€โ”€ style.css        # Minimalist CSS theme

Configuration

App config (src/snekquiz/config/app.yaml) provides default config if no path is provided.

A user specified config file can supplied with:

  • The APP_CONFIG environment variable is read to load a config file, eg export APP_CONFIG=/path/to/config.yaml.
  • Providing -c or --app-config arguments

Logging config (src/snekquiz/config/logging.yaml) provides default logging config.

A user specified config file can supplied with:

  • The LOG_CONFIG environment variable
  • The -l or --log-config arguments

When running with uvicorn you must use the environment variable approach.

Development

# Lint & format
uv run ruff check --fix .
uv run ruff format .

# Type check
uv run ty check

# Pre-commit hooks (using prek)
prek install
prek run --all-files

Theme

Colours: #ffffff ยท #000000 ยท #002554 ยท #099d91 ยท #00cc99

License

See LICENSE.


Built with vibes and Claude Opus 4.6.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snekquiz-0.1.3.tar.gz (20.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

snekquiz-0.1.3-py3-none-any.whl (27.8 kB view details)

Uploaded Python 3

File details

Details for the file snekquiz-0.1.3.tar.gz.

File metadata

  • Download URL: snekquiz-0.1.3.tar.gz
  • Upload date:
  • Size: 20.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for snekquiz-0.1.3.tar.gz
Algorithm Hash digest
SHA256 a773d7ebf54f07f3faec50cb4e776574b52e9e03a7f26ae9fd6a7edc581a9548
MD5 0316659cdd33e091bce1fefa10e201cd
BLAKE2b-256 e831e646950069b82294e4316842758cafeb6e0c6f0cf23c3fa6a164e25cd88e

See more details on using hashes here.

File details

Details for the file snekquiz-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: snekquiz-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 27.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for snekquiz-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ea7bc8c24d4e7f37a9c3089b32acdf32b6065617026642c3f00eaa29f20a9da2
MD5 c1bd846f1eee8f62547ede2c0d5b794c
BLAKE2b-256 daf5a8070f95b0030ee5455248658cd49d12009c3b27624aea0386df75f8155b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page