All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
6.3 KiB
6.3 KiB
Architecture
- Notes live in content and ship to public via Quartz under quartz; Django lives in stroma and hosts the quiz and ingest services.
- Static Quartz pages are configured through quartz.config.ts and layouts in quartz.layout.ts, while Django templates sit in stroma/templates with HTMX-like partials in stroma/templates/partials.
- Data flows: Obsidian markdown → question importer (stroma/quiz/utils/importer.py) → relational models (stroma/quiz/models) → quiz/session views → rendered partials front-end.
Quartz Site Workflow
- Use Node 22+ and npm 10.9+ as enforced in package.json; run
npm installonce, thennpm run docsto build+serve Quartz against thecontentdir. - The CLI is exposed via
npm run quartz/npx quartz ...and reads custom config/theme in quartz.config.ts plus layout definition in quartz.layout.ts. - content follows Obsidian conventions (Swedish folder names, embedded PDFs/CSV) and Quartz ignores private/templates per the
ignorePatternsvalue. - When editing markdown, keep Obsidian-flavored syntax and frontmatter tags because the quiz importer keys off tags like
frågetyp/mcq.
Django Quiz Service
- The project root is stroma; run it with
uv run python manage.py runserver(Python 3.13, deps in stroma/pyproject.toml). - Core models:
QuizSession,QuizResult,QuizUser,Question,Tag,Exam, etc. in stroma/quiz/models; sessions filter questions via stroma/quiz/views/get_session_questions_view.py. - Primary views live in stroma/quiz/views and always expect
request.quiz_user; e.g. stroma/quiz/views/get_next_question_view.py renders partials consumed by thequiz_modepage. - URL routing: stroma/quiz/urls.py registers quiz endpoints under
/quiz/, and stroma/quiz/quiz_urls.py defines per-view paths (session/<id>/question,/next/,/submit/, etc.).
Question Import Pipeline
- stroma/quiz/utils/importer.py parses Obsidian markdown, infers question type via
tags, and stores options/matching_data plus tag slugs; the importer respects file mtimes and tracks stats. - stroma/quiz/utils/watcher.py plus stroma/quiz/apps.py spin up a background Watchdog thread on startup (unless running management commands/tests) targeting
settings.QUESTION_WATCH_PATHfrom stroma/settings.py. - Management commands
uv run python manage.py import_questions [--folder ... --force]andpopulate_examslive in stroma/quiz/management/commands for bulk ingest/backfilling. - The importer expects spoiler blocks for answers and tags like
frågetyp/mcq; missing answers mark the file as TODO and skip DB writes, so keep metadata consistent.
File Uploads & Assets
- The
fileapp exposes/file/upload/+/file/upload/api/via stroma/file/urls.py; UI renders from stroma/file/views/upload_files_page_view.py. - Upload handling in stroma/file/views/upload_files_api_view.py mirrors the client’s folder hierarchy, infers MIME types, stores text content when possible, and persists binaries under
uploads/. - Metadata/state for uploaded artifacts sit in stroma/file/models/file_model.py and are owned by
quiz.QuizUser.
Session & Request Patterns
- stroma/quiz/middleware.py auto-creates
QuizUserrecords tied to Django session keys and attachesrequest.quiz_user; every view assumes this, so never bypass the middleware. QuizResultenforces one row per user+question viaunique_together(stroma/quiz/models/quiz_result_model.py) and normalization logic in submit_answer_view; reuseupdate_or_createwhen recording answers.- Navigational/partial views such as quiz_question_view and navigate_question_view rely on consistent ordering from
get_session_questions; maintain that helper when altering filtering behavior.
Testing & Tooling
- Python deps/tests are run through
uv(uv sync, thenuv run pytest) per stroma/AGENT.md and versions pinned in stroma/pyproject.toml. - Pytest config in stroma/pytest.ini enables
--reuse-dband short tracebacks; stroma/conftest.py switches to in-memory SQLite and provides markdown fixtures for parser tests. - Comprehensive integration coverage exists in stroma/quiz/tests/test_views.py; extend these when touching quiz flows (session creation, submissions, difficulty ratings).
- SQLite WAL is default (see stroma/settings.py); when debugging concurrency, clear
db.sqlite3-wal/shmfiles before reruns.
Coding Conventions
- Follow stroma/AGENT.md: Obsidian-flavored Markdown, no extra docstrings/comments unless asked, favor early returns, narrow
try/except, and keep regexes as upper-case_REconstants with inline comments. - Use type hints everywhere, prefer function-based Django views, and leverage django-stubs/pytest-django for typing/tests.
- When working in markdown ingestion, maintain tag-driven semantics (
frågetyp/*, completion stats) and keep regex patterns centralized in parser modules. - Tests should live beside implementations (e.g.,
quiz/utils/tests) and use parametrizedpytestsubtests when iterating over inputs. - Keep new dependencies declared in
pyproject.toml(Python) orpackage.json(Quartz) and prefer latest stable versions unless compatibility dictates otherwise.