## Step 5: `app.py` + UI Pages (NiceGUI + FastAPI composition) ## Objective Implement the MVP user-facing application layer so users can: 1. Upload a document from the UI 2. Trigger Step 4 upload/job creation flow 3. See live job lifecycle status (`queued`, `processing`, `transcribed`, `failed`) 4. Open a job detail view to read transcript text or failure details This step composes Steps 1–4 into a usable UI. --- ## Architecture Summary (NiceGUI-aligned) Step 5 uses a **FastAPI app factory + lifespan orchestration** and mounts/registers NiceGUI pages via explicit page modules. ### Core architecture decisions - **App factory:** `create_app()` - **Lifespan-managed resources:** worker start/stop managed in startup/shutdown - **Modular pages:** upload and jobs pages in separate modules (no monolithic UI file) - **Health endpoint:** FastAPI-side `/healthz` - **Dependency direction (one-way):** - `app` -> `config/logging/db/worker/ui/api` - `ui/pages` -> `services` - `services` -> `db/models/providers` - no reverse imports from services into UI/API ### DB and AI stance (explicit) - **DB:** already enabled (SQLModel + SQLite), session lifecycle remains request/service-scoped as built in prior steps. - **AI workflow:** already in place via Step 3 transcription service + Step 4 worker; UI does not call provider SDK directly. --- ## Scope ### In scope - `src/transcription/app.py` - `src/transcription/ui/upload_page.py` - `src/transcription/ui/jobs_page.py` - `src/transcription/ui/__init__.py` - `src/transcription/api/health.py` (or equivalent FastAPI health route module) - UI/app tests with MCP scaffold->fill flow ### Out of scope - Auth - advanced filtering/search UX - batch upload UX beyond MVP - deployment/container hardening --- ## Planned Deliverables ### Source files - `src/transcription/app.py` (app factory + lifespan wiring) - `src/transcription/api/health.py` (GET `/healthz`) - `src/transcription/ui/upload_page.py` (upload flow) - `src/transcription/ui/jobs_page.py` (status list + detail) - `src/transcription/ui/__init__.py` (explicit `register_pages(...)` export) ### Test files - `tests/test_app.py` - `tests/api/test_health.py` - `tests/ui/test_pages_registration.py` - `tests/ui/test_upload_page.py` - `tests/ui/test_jobs_page.py` --- ## Implementation Plan + Checklist ## Phase A — App factory and lifespan orchestration - [ ] Create `create_app()` in `src/transcription/app.py` - [ ] Add FastAPI lifespan startup/shutdown handlers - [ ] Startup responsibilities: - [ ] `setup_logging()` - [ ] `create_all()` - [ ] ensure directories exist (`upload_dir`, `prompt_dir`) - [ ] create worker stop event - [ ] start worker background thread/task - [ ] Shutdown responsibilities: - [ ] signal stop event - [ ] join/cleanup worker thread/task cleanly - [ ] Register API router(s), including health route - [ ] Register NiceGUI pages via explicit page registration function ## Phase B — FastAPI health endpoint - [ ] Create `src/transcription/api/health.py` - [ ] Add `GET /healthz` returning simple healthy payload - [ ] Wire route into app factory ## Phase C — Upload page (`ui/upload_page.py`) - [ ] Add upload route/page registration function - [ ] Render file input accepting supported extensions - [ ] On submit: - [ ] show loading/progress state - [ ] call `create_upload_job(filename, file_bytes, ...)` - [ ] show success state with job reference/link - [ ] On error: - [ ] show user-safe error message - [ ] restore ready UI state - [ ] Ensure no blocking calls in UI event handlers beyond bounded service interaction ## Phase D — Jobs page (`ui/jobs_page.py`) - [ ] Add jobs list route/page registration function - [ ] Display jobs with status + timestamps - [ ] Add job detail route/view - [ ] Show transcript on success, error detail on failure - [ ] Include explicit refresh action and loading state - [ ] Ensure error states are surfaced to user and logged ## Phase E — UI registration module - [ ] Update `src/transcription/ui/__init__.py` - [ ] Export `register_pages(...)` - [ ] Ensure each page module exports `register_page(...)` - [ ] Keep page registration explicit and modular --- ## MCP Testing Workflow (Required) Use these resources directly: - `resource://catalog/prompts/pytest-scaffold` - `resource://prompts/pytest-scaffold/document` - `resource://catalog/prompts/pytest-fill-scaffold` - `resource://prompts/pytest-fill-scaffold/document` ## E1 — Scaffold tests first (structure only) Target modules: - `src/transcription/app.py` - `src/transcription/api/health.py` - `src/transcription/ui/upload_page.py` - `src/transcription/ui/jobs_page.py` Scaffold test files: - `tests/test_app.py` - `tests/api/test_health.py` - `tests/ui/test_pages_registration.py` - `tests/ui/test_upload_page.py` - `tests/ui/test_jobs_page.py` Scaffold constraints: - [ ] class/method skeletons only - [ ] one-line docstrings - [ ] concise behavior-focused names - [ ] no implementation assertions yet Validation: - [ ] `uv run pytest --collect-only -q` ## E2 — Fill scaffold tests Fill constraints from MCP guidance: - [ ] preserve scaffold class/method names and docstrings (locked baseline) - [ ] one behavior target per method - [ ] deterministic tests preferred - [ ] minimal mocking; only nondeterministic boundaries Stack: - [ ] `fastapi` (or `mixed` if needed for UI+DB fixture combination) Suggested coverage: ### `tests/api/test_health.py` - [ ] `/healthz` returns success status and expected payload shape ### `tests/ui/test_pages_registration.py` - [ ] page registration wiring succeeds - [ ] expected routes are present ### `tests/test_app.py` - [ ] startup path initializes runtime dependencies - [ ] worker start is invoked on startup - [ ] worker shutdown signal/cleanup is invoked on shutdown ### `tests/ui/test_upload_page.py` - [ ] upload action calls upload service - [ ] success feedback displayed - [ ] error feedback displayed for `UploadError` - [ ] loading/progress state behavior covered ### `tests/ui/test_jobs_page.py` - [ ] list renders job statuses - [ ] detail shows transcript text for successful job - [ ] detail shows error detail for failed job - [ ] refresh/loading state behavior covered Marker strategy: - [ ] `unit` for pure helpers/state formatting - [ ] `integration` for app/page/service+DB contracts - [ ] `external` not required for default Step 5 lane --- ## Validation Sequence (strict) - [ ] `uv run pytest --collect-only -q` - [ ] `uv run pytest -m unit -q` *(if unit tests touched)* - [ ] `uv run pytest tests/api/test_health.py -q` - [ ] `uv run pytest tests/ui/test_pages_registration.py -q` - [ ] `uv run pytest tests/test_app.py -q` - [ ] `uv run pytest tests/ui/test_upload_page.py -q` - [ ] `uv run pytest tests/ui/test_jobs_page.py -q` - [ ] `uv run pytest -q` --- ## Guardrails (NiceGUI + MVP) - [ ] Do not collapse pages into one file. - [ ] Do not use implicit global side effects for runtime wiring. - [ ] Keep UI responsive with explicit loading/progress/error states. - [ ] Do not place provider SDK calls in UI handlers. - [ ] Keep dependency direction one-way and maintainable. --- ## Definition of Done - [ ] App factory + lifespan are in place - [ ] Health endpoint exists and is tested - [ ] Upload page creates queued jobs through service boundary - [ ] Jobs list/detail pages render status/transcript/failure data - [ ] Worker lifecycle is started/stopped by app lifespan - [ ] Scaffold->fill testing flow completed and validated - [ ] Full suite passes: `uv run pytest -q` --- ## PR Checklist (Integrated) ### Implementation - [ ] `app.py` app factory + lifespan implemented - [ ] FastAPI health route (`/healthz`) implemented - [ ] `ui/upload_page.py` implemented - [ ] `ui/jobs_page.py` implemented - [ ] `ui/__init__.py` explicit page registration implemented - [ ] Worker startup/shutdown managed by lifespan ### Testing (MCP-compliant) - [ ] Scaffold phase completed first for all Step 5 tests - [ ] `--collect-only` passed on scaffolds - [ ] Fill phase completed without renaming/re-nesting scaffolded tests - [ ] Marker decisions documented (`unit` vs `integration`) - [ ] Targeted tests passed - [ ] Full suite passed ### Evidence - [ ] Validation command outputs captured - [ ] Files created/updated listed - [ ] MCP prompt resources referenced in implementation notes - [ ] Any residual risks/questions documented ---