# Task: Web Dashboard (FastAPI + Jinja2) ## Description Currently, the only way to monitor the system is via Telegram bot commands or SSH into the server. This task adds a read-only web dashboard for real-time visibility into keywords, ads, users, and stats. ## Architecture ``` ┌──────────────────────────────────────────────┐ │ FastAPI App (port 8766) │ │ │ │ Auth: Basic Auth (WEB_UI_USERNAME/PASSWORD) │ │ Templates: Jinja2 with inline CSS │ │ │ │ Routes: │ │ GET / → Dashboard │ │ GET /keywords → Keywords list │ │ GET /keywords/ → Keyword detail │ │ GET /users → Users list │ │ GET /ads → Recent ads │ │ GET /stats → JSON stats │ └──────────┬───────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────┐ │ PostgreSQL (asyncpg pool) │ │ │ │ Queries: │ │ - Keywords with status, filters, subs │ │ - Recent ads with price, location │ │ - Users with mute/digest settings │ │ - Stats (counts, queue status) │ └──────────────────────────────────────────────┘ ``` ## Implementation Details ### 1. Add dependencies In `worker/requirements.txt`: ``` fastapi==0.115.0 uvicorn==0.30.0 jinja2==3.1.4 ``` ### 2. Create `worker/src/web.py` - FastAPI app with Jinja2 template engine - Basic auth middleware using `WEB_UI_USERNAME` / `WEB_UI_PASSWORD` env vars - Routes that query the DB via `get_pool()` from `db.py` - Each route returns HTML via Jinja2 templates ### 3. Create `worker/src/templates/` - `base.html` — Base layout with sidebar navigation, dark theme - `dashboard.html` — Keywords overview + stats summary cards - `keywords.html` — Table of keywords with status, filters, subscribers - `keyword_detail.html` — Keyword detail with recent ads, price history, scrape logs - `users.html` — Users list with mute/digest settings - `ads.html` — Recent ads with search/filter ### 4. Integrate into `main.py` - Start uvicorn server on port 8766 alongside existing aiohttp health server on 8765 - Graceful shutdown includes web server cleanup ## Acceptance Criteria - [ ] Web UI accessible at `http://:8766` with basic auth - [ ] Dashboard shows keywords with status, filters, subscribers, last scrape - [ ] Dashboard shows recent ads with price, location, keyword - [ ] Dashboard shows users with mute/digest settings - [ ] Dashboard shows stats (ads indexed, notifications sent, queue status) - [ ] Health server still works on port 8765 (no regression) - [ ] Telegram bot still works (no regression)