Skip to content

Elo07/fitforge

Repository files navigation

Fitforge

An AI-powered job application assistant. Upload job postings, get a market analysis, compare your resume against the market, and generate per-posting application reports with fit scores, cover letters, resume rewrites, and interview prep.

Built with FastAPI, Next.js, OpenRouter (LLM), and Tavily (web search).


Features

  • Market Analysis — extracts structured data from job posting PDFs and synthesizes patterns across all postings (skills demand, seniority distribution, company profiles)
  • Resume Gap Analysis — parses your resume and produces a triaged gap report comparing your skills to the market
  • ATS Scorer — simulates keyword-based ATS filtering and shows exactly which keywords were found, missed, or semantically matched
  • Application Advisor — generates a full report for any posting: fit score, resume adaptation advice, cover letter guidance, and interview prep
  • Cover Letter Generator — two complete cover letter drafts (professional and conversational tones) tailored to the posting
  • Resume Rewriter — rewrites your skills and experience bullets for the target posting with a changelog; no fabrication
  • HTML Visual Reports — self-contained HTML report with fit score charts, skill match breakdown, and tabbed cover letter viewer
  • Conversation Mode — interactive Q&A after report generation using full context (posting, resume, gap analysis, market summary)

Setup

Requirements

  • Python 3.11+
  • Node.js 20+
  • uv for Python dependency management
  • A free OpenRouter API key
  • A free Tavily API key

Install dependencies

# Python
uv sync

# Frontend
cd frontend && npm install

Configure environment

cp .env.example .env

Edit .env and set your API keys:

OPENROUTER_API_KEY=your_key_here
TAVILY_API_KEY=your_key_here

Optional settings (with defaults):

APP_PASSWORD=changeme          # Password to access the web UI
OPENROUTER_MODEL=google/gemini-3-flash-preview
LOG_LEVEL=info

Running the Web UI

Start the backend and frontend in separate terminals:

# Terminal 1 — API server (port 8000)
uv run uvicorn src.web.main:app --host 0.0.0.0 --port 8000 --reload

# Terminal 2 — Next.js dev server (port 3000)
cd frontend && npm run dev

Open http://localhost:3000 and log in with your APP_PASSWORD.


CLI Usage

All commands run from the project root. Pass -v / --verbose to any command for debug output.

Phase 1 — Market Analysis

Processes job posting PDFs in data/raw/jobs/ and generates a market report.

uv run python -m src.extract.market
Flag Default Description
--jobs-dir PATH data/raw/jobs Directory containing job posting PDFs
--out-dir PATH data/jobs Directory to save extracted JSON files
--report PATH data/analysis/market_analysis.md Output path for market report
--force off Re-extract all postings even if JSON exists

Re-runnable — skips postings already extracted unless --force is passed.

Phase 2 — Resume Gap Analysis

Parses your resume and produces a gap analysis against the market. Requires Phase 1.

uv run python -m src.analysis.gaps "path/to/resume.pdf"
Flag Default Description
RESUME_PDF (required) Path to your resume PDF
--market-report PATH data/analysis/market_analysis.md Phase 1 market report
--out-dir PATH data/resume Directory for resume JSON
--gap-json PATH data/analysis/gap_analysis.json Output path for gap JSON
--report PATH data/analysis/gap_analysis.md Output path for gap report
--force off Re-run even if outputs exist

ATS Scorer

Scores your resume against a specific job posting using keyword matching.

uv run python -m src.analysis.ats_scorer data/jobs/some_posting.json
Component Weight Method
Required skills 50% Keyword + alias matching
Preferred skills 20% Keyword + alias matching
Experience years 15% Numeric comparison
Education 10% LLM-assisted
Section completeness 5% Presence check

Verdicts: ≥75% → PASS, 50–74% → REVIEW, <50% → REJECT

Phase 3 — Application Advisor

Generates a full application report for a specific posting. Requires Phases 1 and 2.

# Use an existing Phase 1 JSON
uv run python -m src.advisor.advise data/jobs/some_posting.json

# Or provide a new PDF (extracted on the fly)
uv run python -m src.advisor.advise "data/raw/jobs/Some Posting.pdf"
Flag Default Description
POSTING_FILE (required) Job posting JSON or PDF
--cover-letter / --no-cover-letter on Generate 2-tone cover letter
--rewrite / --no-rewrite on Generate tailored resume rewrite
--html / --no-html on Generate HTML visual report
--converse off Enter interactive Q&A after report
--force off Re-extract posting even if JSON exists
# Fast run — report only, no extras
uv run python -m src.advisor.advise data/jobs/some_posting.json \
  --no-cover-letter --no-rewrite --no-html

Deployment

A Dockerfile and railway.json are included for one-command deployment to Railway.

The Docker build compiles the Next.js frontend to static files and serves everything from the FastAPI backend on a single port — no separate frontend server needed in production.

docker build -t fitforge .
docker run -p 8000:8000 --env-file .env fitforge

Project Structure

fitforge/
├── .env.example                # Environment variable template
├── pyproject.toml              # Python dependencies (uv)
├── Dockerfile                  # Multi-stage build (Node + Python)
├── railway.json                # Railway deployment config
│
├── data/
│   ├── raw/jobs/               # Input: job posting PDFs (not committed)
│   ├── jobs/                   # Output: extracted posting JSON (Phase 1)
│   ├── analysis/               # Output: market and gap analysis (Phases 1 & 2)
│   └── resume/                 # Output: parsed resume JSON (Phase 2)
│
├── reports/
│   └── advisor/                # Per-posting advisor reports (Phase 3)
│
├── eval/
│   ├── eval_config.json        # Evaluation test cases
│   └── eval_report.md          # Evaluation output
│
├── frontend/                   # Next.js web UI
│   ├── app/
│   ├── components/
│   └── lib/api.ts              # Typed fetch wrappers for all API routes
│
└── src/
    ├── shared/                 # Config, schemas, LLM client, search, PDF, logging
    ├── extract/                # Phase 1: job posting extraction + market report
    ├── analysis/               # Phase 2: resume parsing, gap analysis, ATS scorer
    ├── advisor/                # Phase 3: advisor, cover letter, rewriter, HTML renderer
    ├── eval/                   # Evaluation harness
    └── web/                    # FastAPI app, routes, auth, session state

Cost

All pipelines are idempotent — re-running without --force reuses cached JSON and skips repeated LLM/API calls.

Phase LLM Calls Tavily Calls Estimated Cost
Phase 1 (9 postings) ~20 ~18 < $0.50
Phase 2 (1 resume) ~2 0 < $0.05
ATS Scorer (1 posting) ~3 0 < $0.02
Phase 3 (1 posting, all extras) ~10 ~2 < $0.20

Default model: google/gemini-3-flash-preview via OpenRouter. Override with OPENROUTER_MODEL in .env.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors