End-to-end workflow platform for the full job application journey: discover, tailor, apply, and track. A Chrome MV3 extension with Shadow DOM isolation, a FastAPI backend on Fly.io, and a 9-page React dashboard - all serving the same user journey from first job page visit to offer.
Applying to jobs at scale requires reading job descriptions, tailoring resumes, filling in identical form fields on every ATS, drafting cover letters, and tracking status across dozens of applications. Each step is manual, repetitive, and context-dependent. At 10 applications per week, this is a part-time job. At 50, it's unsustainable.
Existing tools either scraped job boards (no apply step) or auto-filled forms blindly (no tailoring). Nothing connected discovery to tailoring to submission to tracking as one coherent workflow.
One workflow product instead of three overlapping apps. The Chrome extension, FastAPI backend, and React dashboard all serve the same user journey: find a job, tailor the resume, apply, track the outcome. State flows one direction through the pipeline.
Chrome MV3 content script with Shadow DOM isolation - no CSS collisions with host job pages. MutationObserver fires only on form element additions/removals (not cosmetic DOM changes). Offline Queue drains on reconnect. 11 ATS-specific adapters handle Workday, Greenhouse, Lever, Ashby, LinkedIn, and more.
Multi-provider LLM cascade: Anthropic - OpenAI - Gemini - Groq - Kimi - Ollama - keyword fallback. Per-category model routing dispatches different question types (why_company, cover_letter, strength) to preferred providers. pgvector retrieval grounds answers in prior work history and past high-reward responses.
Every resume (LaTeX source + rendered PDF), every saved answer, and every application is stored in the Vault. Resumes are stored with ATS scores and TF-IDF/embedding vectors. Answers accumulate a reinforcement learning reward score (0.0-1.0) based on whether the user accepted them as-is, edited them, or regenerated.
High-reward answers (score >= 0.8) from the same company or question category are injected into future LLM prompts as style examples - personalization without model fine-tuning. Resume versioning tracks which resume was used for which application, with GitHub commit SHAs as the audit trail.
A key engineering decision: the system never depends on a single LLM provider being available. The cascade tries providers in priority order. "Enabled" means having an API key - not a separate boolean flag (a design flaw I discovered and fixed in Phase 7). The cascade degrades gracefully to keyword-based answer generation when all providers fail or are unconfigured.
Per-category model routing lets users route different question types to different providers.
Cover letters go to Claude for quality. Simple fields go to Groq for speed. The routing is
stored in chrome.storage.local as categoryModelRoutes
and applied at generation time.
Phase 8 is complete: 355 backend tests, 0 TypeScript errors, 9-page dashboard on Vercel, floating panel live on Fly.io. Four P0 security issues are tracked before public launch: an unauthenticated register endpoint, JWT bypass when Clerk URL is unset, offline queue hardcoded to localhost, and CORS wildcard when extension ID is unset.
Next: fix the P0 issues, complete Dashboard v2, and wire the tailor-resume API call into the answer generation flow for seamless resume tailoring during application.