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.1.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.1-py3-none-any.whl (28.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: snekquiz-0.4.1.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.1.tar.gz
Algorithm Hash digest
SHA256 02297a80f0669f6bf08ca1b1902bc37a446303e6f8fc5f24b525e9cc32912336
MD5 76a611f92c334c9b993e4ba1381c7146
BLAKE2b-256 6d9b8f7f9ba430a85c320b3b9aad0e687efbe226c3830e6acdde49cd751d4b61

See more details on using hashes here.

Provenance

The following attestation bundles were made for snekquiz-0.4.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: snekquiz-0.4.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bd4384a1d5aaa2fd2df99afb4563523d27f47940760fe0726f2c2e8175de1589
MD5 ff8ec8844a6c57b14dbcff11699a8ffa
BLAKE2b-256 0c7b5b60e4ec63c9024ab140f210deef9019c03708be458488625917bb14d6c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for snekquiz-0.4.1-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