# Copilot instructions for scenar-creator ## Big picture (read this first) - This is a single FastAPI service that serves both API and static frontend (no separate frontend build step). - Entry point: `app/main.py` mounts `/static` and serves `index.html` at `/`. - API boundary is under `app/api/` (`/api/health`, `/api/validate`, `/api/sample`, `/api/generate-pdf`). - Core domain object is `ScenarioDocument` in `app/models/event.py` (JSON-first design, no DB). - PDF rendering is the main backend logic in `app/core/pdf_generator.py` (ReportLab canvas, A4 landscape timetable). ## Data model and domain rules (project-specific) - Multi-day events use `event.date_from` + `event.date_to`; keep backward compatibility with legacy `event.date`. - `blocks[].date` is always a concrete day (`YYYY-MM-DD`) even for multi-day events. - Overnight blocks are valid: `end <= start` means crossing midnight. This rule exists in frontend canvas and backend PDF. - `series_id` groups blocks created by “add to all days”; deleting a series removes all blocks with matching `series_id`. - `program_types[].id` must match each `blocks[].type_id`; unknown types are validation errors. ## Frontend architecture conventions - Frontend is vanilla JS globals loaded in order from `index.html`: `API` -> `Canvas` -> import/export helpers -> `App`. - `App.state` is the source of truth (`event`, `program_types`, `blocks`) in `app/static/js/app.js`. - Canvas timeline is horizontal time axis with 15-minute snapping (`Canvas.GRID_MINUTES = 15`) in `app/static/js/canvas.js`. - Drag/resize behavior: native pointer drag for move + interact.js resize handle for duration updates. - UI copy and date labels are Czech (e.g., `Pondělí (20.2)`), so preserve localization in new UI text. ## Backend conventions - Keep API handlers thin; place formatting/rendering logic in `app/core/`. - Raise `ScenarsError` from core logic and translate to HTTP 422 in API (`app/api/pdf.py`). - PDF generator handles: - legend from `program_types` - optional responsible person text inside blocks - notes as superscript markers + optional page 2 note listing - Czech diacritics in PDFs rely on LiberationSans registration with Helvetica fallback. ## Developer workflows - Local run: `uvicorn app.main:app --reload --port 8080` - Tests: `python3 -m pytest tests/ -v` - Container image includes required fonts (`fonts-liberation`) in `Dockerfile`; do not remove unless PDF text rendering is reworked. - Health endpoint for local/container checks: `/api/health`. ## Testing patterns to preserve - API tests use `fastapi.testclient.TestClient` (`tests/test_api.py`). - PDF tests assert magic header `%PDF-` and page count with regex (`tests/test_pdf.py`). - Keep coverage for overnight blocks, multi-day ranges, legacy `event.date`, and `series_id` behavior when changing models/UI. ## High-impact files - `app/core/pdf_generator.py` — timeline layout math, fonts, notes page logic. - `app/static/js/canvas.js` — drag/resize + time-range computation. - `app/static/js/app.js` — modal save/delete logic, series expansion, document import/export shape. - `app/models/event.py` — schema contract used by both API and frontend JSON.