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

Uploaded Python 3

File details

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

File metadata

  • Download URL: snekquiz-0.4.0.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.0.tar.gz
Algorithm Hash digest
SHA256 5180cfdbc47d3b774f73f62e03dcf7a51dc779d1c136e83be22bf14ac8c1335a
MD5 5723d3e0ae08ede7815453c464aa5769
BLAKE2b-256 d5643b1e78eb0ff779bbdbd295a431d661cb478e3c282ee450607a071aa8369e

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: snekquiz-0.4.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 996ba641fafae14b8430db283db3598e11dcd814f1d49bd5f8f26a989ab10470
MD5 fa7f3b5aa7f17653963d1487b9598a38
BLAKE2b-256 96011323a867e3ff410bfaf1f1df34f52ab8bb07e8969c47aaab20bf65363847

See more details on using hashes here.

Provenance

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