Skip to content

MK023/JobSearch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

565 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Job Search Command Center

CI Python FastAPI PostgreSQL Tests mypy License

AI-powered job search platform. Paste your CV, analyze job postings, get compatibility scores, gap analysis, interview prep, cover letters, and automated outreach tools. Query your data from Claude Desktop via MCP.

Live | API


Why

Built after 96 manual job applications turned into a data problem I couldn't solve in a spreadsheet. I needed to track which job descriptions actually matched my profile, which gaps were "bridgeable" versus structural, which interview formats worked, and how my conversion rate evolved with rebrand decisions — across multiple recruiters, multiple roles, and a 4-month window. JobSearch is the toolchain I built to convert job-search from intuition-driven to data-driven.

The architecture is the actual portfolio. The bot itself is the customer who happens to be me — eating the dogfood every time I triage a new posting. It runs on the same stack I use professionally (FastAPI + PostgreSQL + cloud-native deploy + Claude API via MCP), with the same security and CI discipline that I'd apply at scale (OWASP Top 10 audit, mypy strict, 11 CI checks, daily backups, audit trail). Building this while searching for the job is the meta-loop: the data the system collects refines my own approach in real time.


Operating cost

Production deployment runs at ~$3-5/month total — pay-per-use AI costs only:

Component Cost Notes
Render.com web service (Frankfurt) Free 750 hours/month free tier — covers single-tenant 24/7
Neon PostgreSQL (serverless) Free 1 GB free tier with autosuspend
Cloudflare R2 (DB backups) Free 10 GB / 1M ops free tier
Anthropic Claude API ~$3-5/month Pay-per-use: Haiku at ~$0.005/analysis, Sonnet at ~$0.02/analysis
Resend (email reminders) Free 100 emails/day free
RapidAPI (Glassdoor, salary, news) Free Free tier with caching (30-day TTL reduces ~90% of calls)
Sentry (error tracking) Free Free tier with 20% trace sampling
Checkly (6 uptime checks, Terraform IaC) Free Free tier
Domain jobsearches.cc ~$15/year Cloudflare Registrar (at cost)

The architecture is intentionally designed to fit under $10/month total — but every cost-engineering decision is reversible. Swap Render for ECS Fargate, swap Neon for RDS, and the same Docker image deploys to a $200/month enterprise setup without a single code change. Cheap by design, not by accident.


Architecture

  Claude Desktop          Browser              GitHub Actions
       |                     |                  (CI + daily backup)
       v                     |                        |
  +---------------+          |                        |
  |  MCP Server   |          |                        |
  | (local, stdio)|          |                        |
  | 15 read-only  |          |                        |
  | tools, proxy  |          |                        |
  +-------+-------+          |                        |
          | HTTP (X-API-Key) |                        |
          v                  v                        v
  +----------------------------------+     +------------------+
  |       FastAPI + Jinja2           |---- | Claude API       |
  |    (Render.com, Frankfurt)      |---- | Cloudflare R2    |
  |                                  |---- | Resend (email)   |
  |                                  |---- | RapidAPI         |
  +---------------+------------------+     +------------------+
                  |
           +------+------+          +------------------+
           |              |          | Checkly (6 checks|
     +-----v------+  +----v----+    | Terraform IaC)   |
     | PostgreSQL |  |  Redis  |    +------------------+
     |  (Neon)    |  |  (opt)  |
     +------------+  +---------+

The MCP server runs locally on macOS via Claude Desktop (stdio transport). It is a thin HTTP proxy (~120 lines) — every tool is a single HTTP call to the backend. The backend on Render.com does everything: AI analysis via Anthropic API (tool-use schema-driven JSON), PostgreSQL persistence (Neon), deduplication, cost tracking, and serves the web UI. Checkly monitors uptime via 6 checks managed as Terraform IaC. Daily DB backups run via GitHub Actions cron to Cloudflare R2.


Features

Feature Description
AI Analysis Claude Haiku/Sonnet scores CV-to-job compatibility (0-100)
Career Track Classification Each job tagged as plan_a_devops / plan_b_dev / hybrid_a_b / cybersec_junior_ok / out_of_scope (colored chip in detail view)
Gap Analysis Structured gaps with severity, bridgeability, and action plan
Interview Prep Likely questions + suggested answers based on your CV
Cover Letter Multi-language, context-aware (uses analysis results)
Follow-up Email/LinkedIn Automated outreach scaled to days since application
Multi-round Interviews Per-round scheduling (conoscitivo/tecnico/finale) with outcome tracking (passed/rejected/withdrawn)
Dashboard 8 widgets: follow-up, interviews, Cowork, activity, news, to-do, top 5, DB usage
Agenda To-do page with DB-backed task management
Notification Center Server-side computed rules (interviews, budget, outcomes, DB size, followup, backlog) with dismiss/undismiss
Stats Page 9 Chart.js charts: funnel, score distribution, timeline, top companies, work mode, contract split, recommendation, spending
Analytics Page /analytics — unlocks every 15 new triaged analyses. Computes discriminants and bias signals, persists snapshots in analytics_runs, and updates the learned user_profiles row
Auto-Adapt Prompt Learned prompt_snippet from user_profiles is auto-prepended to every Claude analysis call, self-tuning the tool based on past decisions
Admin Panel Operational parameters, maintenance tools, diagnostics
Internal Metrics Request metrics middleware + admin metrics dashboard
Settings AI preferences (model, budget), app preferences persisted in DB
File Upload Document upload via Cloudflare R2 with presigned URLs
Document Scanner Claude API checks if uploaded documents are filled in
Email Reminder Resend notifies about unfilled documents
Batch Analysis Persistent PostgreSQL queue, survives crashes and autostop
Recruiter Contacts Per-application CRM: name, email, phone, LinkedIn
Company Enrichment Glassdoor rating via RapidAPI with 30-day cache
Salary Estimates Job Salary Data API with location fallback and 30-day cache
Company News Real-Time News Data API with 7-day cache + dedicated /news page
Status "rifiutato" Rejected-by-company status for complete funnel tracking
Cost Tracking Per-analysis cost, daily totals, configurable budget
DB Usage Monitoring Track PostgreSQL usage against 1GB free tier limit
DB Backup Manual + daily cron (GitHub Actions) to Cloudflare R2
DB Cleanup Delete old low-score analyses to free 1GB storage (dry-run default)
Audit Trail DB log of all user actions
Claude MCP 15 read-only tools to query data from Claude Desktop

Tech Stack

Layer Technology
Backend FastAPI + Uvicorn + Jinja2 SSR
Frontend Alpine.js (reactive UI) + Chart.js 4.4 (stats) + vanilla JS modules
ORM SQLAlchemy 2.0 (Mapped[X] typing) + Alembic (26 migrations)
Database PostgreSQL 17 (Neon serverless, 1GB free tier)
Cache Redis 7 (optional, graceful degradation)
AI Anthropic Claude API (tool-use schema-driven JSON, prompt v7 candidate-aware + career-track + auto-adapt)
Analytics Pure-Python data-science primitives (backend/src/analytics/, no external deps) + /analytics page (backend/src/analytics_page/) + CLI scripts (scripts/export_db.py, scripts/analyze_db.py)
File Storage Cloudflare R2 (S3-compatible, presigned URLs, DB backups)
Email Resend (document reminders)
Auth Session + bcrypt + rate limiting (slowapi) for web UI; API key (X-API-Key) for MCP
MCP FastMCP (local, stdio) — 15 read-only tools, thin HTTP proxy
Error Tracking Sentry (FastAPI auto-integration, 20% trace sampling)
Monitoring Checkly (6 checks, Terraform IaC)
CI/CD GitHub Actions, 11 check (ruff, ruff format, mypy strict, bandit, pip-audit, stylelint, ESLint, CodeQL 3 lang, SonarCloud QG, pytest, Docker build) + daily backup cron + weekly cleanup
Deploy Render.com (Frankfurt, Docker) + Cloudflare (DNS, R2, HSTS)
IaC Terraform (Checkly monitoring)

Security

  • OWASP Top 10 audit passing (all 10 categories)
  • Content-Security-Policy (CSP) with script/style/font/img whitelist
  • Permissions-Policy (camera, microphone, geolocation denied)
  • HSTS preload (2 years, includeSubDomains) + X-Content-Type-Options + X-Frame-Options
  • UUID validation on all path parameters (anti-injection)
  • Pydantic schema validation on all inputs (email regex, URL whitelist, enum whitelist)
  • Rate limiting: 60/min global, 10/min AI routes, 5/min login
  • Login lockout after failed attempts
  • bcrypt password hashing + session-based auth + CSRF protection for web UI
  • API key auth (X-API-Key header) for MCP-to-backend calls
  • HTTPS only (force_https=true)
  • TrustedHost middleware + restrictive CORS origins
  • DB audit trail for all user actions
  • Bandit security scanning + pip-audit in CI
  • mypy strict on all modules (0 errors)
  • Input size limits (CV 100KB, job description 50KB)
  • API key rejection when unconfigured (prevents auth bypass)
  • BOLA protection on batch item status updates
  • Field-level input validation (max_length on all import fields)
  • URL scheme validation on job URLs
  • Budget hard stop: analysis blocked when budget exhausted
  • Impeccable.style CSS audit + anti-pattern removal

Quick Start

git clone https://github.com/MK023/JobSearch.git
cd JobSearch
cp .env.example .env
# Configure: ANTHROPIC_API_KEY, ADMIN_EMAIL, ADMIN_PASSWORD
docker compose up -d

Open http://localhost — log in with your admin credentials.


Infrastructure

The app is deployed on Render.com (Frankfurt region) as a Docker web service with auto-deploy on push to main. PostgreSQL is hosted on Neon (serverless, 1GB free tier). Cloudflare handles DNS, R2 storage, and HSTS. Checkly monitors uptime (6 checks, Terraform IaC). GitHub Actions runs CI (11 checks) + daily DB backup cron.

# Environment variables on Render:
ANTHROPIC_API_KEY, SECRET_KEY, ADMIN_EMAIL, ADMIN_PASSWORD,
DATABASE_URL (from Neon), REDIS_URL (optional),
R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ENDPOINT_URL, R2_BUCKET_NAME,
API_KEY (for MCP auth), RESEND_API_KEY, SENTRY_DSN,
RAPIDAPI_KEY, TRUSTED_HOSTS, CORS_ALLOWED_ORIGINS

Alembic migrations run automatically on deploy (Dockerfile entrypoint).


Per-analysis AI cost (detail)

Model Per analysis Follow-up
Haiku 4.5 ~$0.005 ~$0.001
Sonnet 4.5 ~$0.02 ~$0.001

See Operating cost section above for the full breakdown including free-tier components.


Documentation

Doc Contents
docs/technical.md 1500-line technical deep dive — 16 sections covering architecture, DB schema, security, AI integration, CI/CD, MCP wiring, learning loop
docs/architecture.drawio Editable system diagram (draw.io / diagrams.net) — single source of truth for the picture rendered in this README
docs/LOCAL_DEV.md Local development setup: Docker Compose, pyenv, pre-commit hooks, debugging Sentry off

License

MIT

About

AI-powered job search platform — CV analysis, gap analysis, interview prep, cover letters, automated outreach. FastAPI + Claude API + MCP.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors