Skip to main content

A minimalist MCQ quiz web application

Project description

SnekQuiz ๐Ÿ

Python 3.13 Ruff ty pre-commit Coverage

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

  • Simple auth โ€“ HTTP Basic. Admins can do admin things, users can take quizzes
  • Quiz list โ€“ See what's available, what you've finished, what's left to do
  • One question at a time โ€“ HTMX gives you instant feedback without page reloads
  • Results โ€“ Your score, what you got wrong, what the right answers were
  • Admin stuff โ€“ Upload quizzes (JSON), see how everyone's doing, delete quizzes when needed
  • API โ€“ POST new quizzes, GET quiz lists, DELETE when you messed up
  • SQLite โ€“ Because sometimes simple is better. No database server required
  • YAML config โ€“ Tweak settings without touching code

Quick Start

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

# Run the app (default: http://0.0.0.0:8001)
uv run snekquiz

# or run via the CLI entry-point
snekquiz

# or via python -m
python -m snekquiz

# Run with custom host/port, SSL, auto-reload for development
snekquiz --host localhost --port 8000 --ssl_keyfile key.pem --ssl_certfile cert.pem --reload

# Run with custom config files
snekquiz --config /path/to/app.yaml --log-config /path/to/logging.yaml

# or via uvicorn directly. NB this will expect `uvicorn` CLI args only
uvicorn snekquiz:create_app --factory --host 0.0.0.0 --port 8001

The server starts at http://0.0.0.0:8001 by default. 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://0.0.0.0:8001/admin.

Adding Quizzes

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:8001/api/quizzes

Quiz format is pretty straightforward:

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 be supplied with:

  • The APP_CONFIG environment variable: export APP_CONFIG=/path/to/config.yaml
  • The --config (or -c) CLI argument: snekquiz --config /path/to/config.yaml

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

A user specified config file can be supplied with:

  • The LOG_CONFIG environment variable: export LOG_CONFIG=/path/to/logging.yaml
  • The --log-config (or -l) CLI argument: snekquiz --log-config /path/to/logging.yaml

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

CLI Arguments

snekquiz --help

Available options:

  • --config, -c: Path to app config YAML (default: bundled config/app.yaml)
  • --log-config, -l: Path to logging config YAML (default: bundled config/logging.yaml)
  • --host: Host to bind to (default: 0.0.0.0)
  • --port: Port to bind to (default: 8001)
  • --reload: Enable auto-reload for development
  • --ssl_keyfile: Path to SSL key file
  • --ssl_certfile: Path to SSL certificate file

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

White, black, navy, teal, and more teal: #ffffff ยท #000000 ยท #002554 ยท #099d91 ยท #00cc99

License

See LICENSE.


Made with questionable judgment 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.4.2.tar.gz (21.3 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.4.2-py3-none-any.whl (28.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: snekquiz-0.4.2.tar.gz
  • Upload date:
  • Size: 21.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for snekquiz-0.4.2.tar.gz
Algorithm Hash digest
SHA256 3c8d019e9220410fcf5a6192e468f51aebc215073ec94aa8741f9629b530bfea
MD5 75cad0ae8faf5ec12c585da4077a8ee5
BLAKE2b-256 d390142a06e5d7eccc4855a002133ce326da6eb1112bb2cf2a2cc46751979a4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for snekquiz-0.4.2.tar.gz:

Publisher: python-publish.yaml on ac3673/SnekQuiz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: snekquiz-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 28.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for snekquiz-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 153a7c0b49e04e3f510ea7a5b57abd0aee9ae3f11d954d007d639002d78c58cc
MD5 33c626544289b5069b07db8c10313d24
BLAKE2b-256 ec3c8398223a0995eb40413172ca700b7364fab7fa0a1cae0f40e9d5733f2d4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for snekquiz-0.4.2-py3-none-any.whl:

Publisher: python-publish.yaml on ac3673/SnekQuiz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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