# Web UI Knowledge Base **Generated:** 2026-05-03 22:15 UTC **Commit:** 41f2a3d **Branch:** feature/tests ## Overview FastAPI Jinja2 web UI layer with Keycloak auth integration, flash messages, and theme support. ## Structure ``` app/presentation/web/ ├── __init__.py ├── auth.py # Keycloak OAuth login/logout/callback ├── deps.py # Web dependency injection (current_user, require_auth) ├── error_handlers.py # HTTP exception handlers for web routes ├── flash.py # Flash message middleware └── routes.py # All web page routes (largest file in project) ``` ## Where to Look | Task | Location | |------|----------| | Add a new page | `routes.py` | | Change auth flow | `auth.py` | | Change flash messages | `flash.py` | | Change error pages | `error_handlers.py` | | Change DI for web | `deps.py` | ## Conventions - **Templates**: Jinja2 in `app/presentation/templates/` - **data-testid attributes REQUIRED** on all interactive elements - **Theme support**: Light/dark via `data-theme` on ``, LocalStorage persistence - **Auth**: HTTP-only cookie `access_token`, Keycloak integration - **Mock data**: Routes currently use `MockPost`/`MOCK_POSTS` — integrate real use cases when ready ## Anti-Patterns - Do NOT use inline comments — self-documenting code only - Do NOT add external CDN dependencies — all assets must be in `static/` - Do NOT bypass `filter_visible_posts()` for draft access control ## Notes - `routes.py` is the largest file in the project (519 lines) — consider splitting by concern - `home`, `list_posts`, `post_detail`, `new_post_form`, `edit_post_form`, `create_post`, `update_post`, `delete_post`, `profile`, `about` are all defined in `routes.py` - Web routers are imported directly in `main.py`, bypassing `app/presentation/__init__.py`