# Job Seeker Platform — Web UI Design **Date:** 2026-02-20 **Status:** Approved ## Overview A Streamlit multi-page web UI that gives Alex (and her partner) a friendly interface to review scraped job listings, curate them before they hit Notion, edit search/LLM/Notion settings, and fill out her AIHawk application profile. Designed to be usable by anyone — no technical knowledge required. --- ## Architecture & Data Flow ``` discover.py → SQLite staging.db (status: pending) ↓ Streamlit UI review / approve / reject ↓ "Sync N approved jobs" button ↓ Notion DB (status: synced) ``` `discover.py` is modified to write to SQLite instead of directly to Notion. A new `sync.py` handles the approved → Notion push. `db.py` provides shared SQLite helpers used by both scripts and UI pages. ### SQLite Schema (`staging.db`, gitignored) ```sql CREATE TABLE jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, company TEXT, url TEXT UNIQUE, source TEXT, location TEXT, is_remote INTEGER, salary TEXT, description TEXT, match_score REAL, keyword_gaps TEXT, date_found TEXT, status TEXT DEFAULT 'pending', -- pending / approved / rejected / synced notion_page_id TEXT ); ``` --- ## Pages ### Home (Dashboard) - Stat cards: Pending / Approved / Rejected / Synced counts - "Run Discovery" button — runs `discover.py` as subprocess, streams output - "Sync N approved jobs → Notion" button — visible only when approved count > 0 - Recent activity list (last 10 jobs found) ### Job Review - Filterable table/card view of pending jobs - Filters: source (LinkedIn/Indeed/etc), remote only toggle, minimum match score slider - Checkboxes for batch selection - "Approve Selected" / "Reject Selected" buttons - Rejected jobs hidden by default, togglable - Match score shown as colored badge (green ≥70, amber 40–69, red <40) ### Settings Three tabs: **Search** — edit `config/search_profiles.yaml`: - Job titles (add/remove tags) - Locations (add/remove) - Boards checkboxes - Hours old slider - Results per board slider **LLM Backends** — edit `config/llm.yaml`: - Fallback order (drag or up/down arrows) - Per-backend: URL, model name, enabled toggle - "Test connection" button per backend **Notion** — edit `config/notion.yaml`: - Token field (masked, show/hide toggle) - Database ID - "Test connection" button ### Resume Editor Sectioned form over `aihawk/data_folder/plain_text_resume.yaml`: - **Personal Info** — name, email, phone, LinkedIn, city, zip - **Education** — list of entries, add/remove buttons - **Experience** — list of entries, add/remove buttons - **Skills & Interests** — tag-style inputs - **Preferences** — salary range, notice period, remote/relocation toggles - **Self-Identification** — gender, pronouns, veteran, disability, ethnicity (with "prefer not to say" options) - **Legal** — work authorization checkboxes `FILL_IN` fields highlighted in amber with "Needs your attention" note. Save button writes back to YAML. No raw YAML shown by default. --- ## Theme & Styling Central theme at `app/.streamlit/config.toml`: - Dark base, accent color teal/green (job search = growth) - Consistent font (Inter or system sans-serif) - Responsive column layouts — usable on tablet/mobile - No jargon — "Run Discovery" not "Execute scrape", "Sync to Notion" not "Push records" --- ## File Layout ``` app/ ├── .streamlit/ │ └── config.toml # central theme ├── Home.py # dashboard └── pages/ ├── 1_Job_Review.py ├── 2_Settings.py └── 3_Resume_Editor.py scripts/ ├── db.py # new: SQLite helpers ├── sync.py # new: approved → Notion push ├── discover.py # modified: write to SQLite not Notion ├── match.py # unchanged └── llm_router.py # unchanged ``` Run: `conda run -n job-seeker streamlit run app/Home.py` --- ## New Dependencies None — `streamlit` already installed via resume_matcher deps. `sqlite3` is Python stdlib. --- ## Out of Scope - Real-time collaboration - Mobile native app - Cover letter editor (handled separately via LoRA fine-tune task) - AIHawk trigger from UI (run manually for now)