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.3.0.tar.gz (21.2 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.3.0-py3-none-any.whl (28.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for snekquiz-0.3.0.tar.gz
Algorithm Hash digest
SHA256 44e759ccedbabb79a5e1582945d063ddc1b9a5ea6c745a687ffbd13bf1471511
MD5 4dea5153185d18cdf58c04612f228b52
BLAKE2b-256 68cecdf6e3efa10b81f7248e9a54bf0192fe15c43f073dcecdae76faf604c382

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: snekquiz-0.3.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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dcbc8f24e493846df0193f34f46254c744653188e66f48d2959a0d7cf04866c5
MD5 23f53601cd9b04ebfd4b2ca52498e47b
BLAKE2b-256 b0043584a78a0b9c97d4ee9f2a06a719fb9b4ab168d47b51381c88daa06b495e

See more details on using hashes here.

Provenance

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