improved-JD-application

CV & Cover Letter AI Optimizer

Supercharge your job applications with AI. Upload your CV once, provide any job description, and receive a tailored ATS-optimised CV and a bespoke cover letter as download-ready PDFs — in under a minute.

Python Flask OpenAI License: MIT


Table of Contents

  1. Project Details
  2. Scope
  3. How It Works
  4. Tech Stack
  5. Project Structure
  6. How to Run the Application
  7. How to Use the Application
  8. Running Tests
  9. Environment Variables
  10. Security Notes
  11. Roadmap
  12. License

Project Details

CV & Cover Letter AI Optimizer is an open-source, AI-powered web application designed to eliminate the tedious manual work of tailoring job applications. Most candidates send the same CV to every role — and most automated screening tools (ATS) reject these generic applications before a human ever reads them.

This tool solves that problem in three steps:

  1. Parse – it extracts structured information (contact details, work history, skills, education) from your existing CV PDF using pdfplumber and OpenAI GPT-4o.
  2. Optimise – it rewrites your professional summary, reorders and strengthens skills, and rewrites experience bullet points to naturally embed keywords and phrases from the target job description, without inventing qualifications you don’t have.
  3. Deliver – it renders two professionally formatted, ATS-friendly PDFs (optimised CV + personalised cover letter) that you can download individually or as a single ZIP bundle.

Key Highlights

Feature Detail
AI engine OpenAI GPT-4o — state-of-the-art reasoning for nuanced rewrites
ATS-friendly output Single-column layout, plain language, no graphics — passes automated screening
JD input flexibility Paste a job-board URL or paste raw JD text
Zero data persistence CV bytes never hit disk; generated PDFs are ephemeral
Single-page UI Clean, drag-and-drop interface — no account required
Fully tested Unit & integration test suite with mocked LLM calls

Scope

In Scope

Out of Scope (current version)


How It Works

Upload CV (PDF)  +  Paste JD (URL or text)
        │
        ▼
  Extract CV text  ──►  Fetch / clean JD text
  (pdfplumber)          (requests + BS4)
        │
        ▼
   GPT-4o analyses CV  →  structured JSON
   (name, email, phone, skills, experience …)
        │
        ▼
   GPT-4o optimises CV against JD
   (rewritten summary, ATS keywords, stronger bullets)
        │
        ▼
   GPT-4o generates Cover Letter
   (personalised, max 400 words, professional tone)
        │
        ▼
  ReportLab renders PDF (CV)   +   PDF (Cover Letter)
        │
        ▼
  Download individually  ──or──  Download as ZIP bundle

Tech Stack

Layer Technology Version
Web framework Flask 3.1
AI / LLM OpenAI GPT-4o via openai 1.68
PDF parsing pdfplumber 0.11
PDF generation ReportLab 4.3
Web scraping requests + BeautifulSoup4 2.32 / 4.13
Configuration python-dotenv 1.1
WSGI utilities Werkzeug 3.1
Testing pytest + pytest-mock 8.3 / 3.14

Project Structure

improved-JD-application/
│
├── app.py                      # Flask entry point — all HTTP routes
│                               #   GET  /                  → serve UI
│                               #   POST /generate          → run AI pipeline
│                               #   GET  /download/<id>/<type>  → serve PDF
│                               #   GET  /download/<id>/bundle  → serve ZIP
│
├── requirements.txt            # Pinned Python dependencies
├── .env.example                # Template for required environment variables
├── .gitignore                  # Excludes .env, uploads/, outputs/, __pycache__
│
├── src/                        # Core business logic
│   ├── __init__.py
│   ├── cv_processor.py         # PDF text extraction (pdfplumber) and
│   │                           # regex-based contact detail parsing
│   │                           # (email, phone, LinkedIn URL)
│   │
│   ├── jd_processor.py         # Fetch JD from URL (requests + BeautifulSoup)
│   │                           # or sanitise plain-text JD input
│   │
│   ├── llm_service.py          # OpenAI GPT-4o client (thread-safe singleton)
│   │                           # — analyse_cv()         → structured JSON
│   │                           # — optimise_cv()        → ATS-tuned JSON
│   │                           # — generate_cover_letter() → plain text
│   │
│   └── pdf_generator.py        # ReportLab PDF renderer
│                               # — generate_cv_pdf()          → CV PDF
│                               # — generate_cover_letter_pdf() → CL PDF
│
├── templates/
│   └── index.html              # Jinja2 single-page web UI
│
├── static/
│   ├── css/style.css           # UI styles (responsive, clean)
│   └── js/main.js              # Form handling, progress indicator,
│                               # download button activation
│
├── tests/
│   ├── __init__.py
│   └── test_app.py             # pytest unit & integration tests
│                               # (all LLM calls mocked via pytest-mock)
│
├── uploads/                    # Reserved for future disk-based upload handling
│                               # (currently CV bytes are processed in memory)
└── outputs/                    # Ephemeral generated PDF / ZIP output files

How to Run the Application

Prerequisites


1. Clone the Repository

git clone https://github.com/shamir456/improved-JD-application.git
cd improved-JD-application

2. Create and Activate a Virtual Environment

# macOS / Linux
python -m venv .venv
source .venv/bin/activate

# Windows (PowerShell)
python -m venv .venv
.venv\Scripts\Activate.ps1

3. Install Dependencies

pip install -r requirements.txt

4. Configure Environment Variables

cp .env.example .env

Open .env in your editor and fill in the required values:

OPENAI_API_KEY=sk-...          # Required — your OpenAI key
FLASK_SECRET_KEY=change-me     # Required — any long random string
FLASK_DEBUG=False              # Optional — set True for hot-reload in dev
MAX_UPLOAD_SIZE_MB=10          # Optional — max CV file size (default 10 MB)
UPLOAD_FOLDER=uploads          # Optional — directory for uploads
OUTPUT_FOLDER=outputs          # Optional — directory for generated PDFs

Tip: Generate a strong secret key with:

python -c "import secrets; print(secrets.token_hex(32))"

5. Start the Server

Development mode

python app.py

The app starts on http://localhost:5000.
Set FLASK_DEBUG=True in .env to enable auto-reload on code changes.

Production mode (using Gunicorn)

pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 app:app

Note: Always set a stable FLASK_SECRET_KEY in production; the auto-generated key is invalidated on every restart.


How to Use the Application

Once the server is running, open http://localhost:5000 in your browser.

Step-by-step Guide

Step Action Detail
1 Upload your CV Drag & drop a PDF onto the upload area, or click Browse to select a file. The file must be a text-based PDF (not a scanned image) and must not exceed the configured size limit (default: 10 MB).
2 Provide the Job Description Choose one of two methods:
  Paste a URL Select the URL tab and paste the full link to the job posting (e.g. a LinkedIn or Indeed listing). The app will fetch and extract the JD text automatically.
  Paste raw text Select the Text tab and paste the full job description text directly into the text area.
3 Generate Click the Generate Optimized CV & Cover Letter button. A progress indicator will appear.
4 Wait ~30–60 seconds The AI pipeline runs three sequential GPT-4o calls: CV analysis → CV optimisation → cover letter generation.
5 Download your documents Once complete, three download buttons appear:
  Optimized CV Downloads Optimized_CV.pdf — ATS-tuned, keywords aligned to the JD.
  Cover Letter Downloads Cover_Letter.pdf — personalised, professional, max 400 words.
  Download Bundle (ZIP) Downloads Application_Bundle.zip containing both PDFs in one file.

Tips for Best Results


Running Tests

pytest tests/ -v

The test suite uses pytest-mock to patch all OpenAI API calls so no real key is needed.

Tests cover:

Area What is tested
cv_processor PDF text extraction from file path and bytes; email, phone, LinkedIn regex extraction
jd_processor URL validation and HTTP error handling; plain-text cleaning and blank-line collapsing
pdf_generator CV PDF generation with full and minimal data; cover letter PDF generation
app routes Missing CV / JD validation; JD URL and text modes with mocked LLM; all download endpoints; ZIP bundle; 404 / 413 error handlers

To run a specific test file or test:

# Run only a specific test
pytest tests/test_app.py::test_generate_success -v

# Run with coverage (requires pytest-cov)
pip install pytest-cov
pytest tests/ --cov=src --cov-report=term-missing

Environment Variables

Variable Required Default Description
OPENAI_API_KEY Your OpenAI API key (GPT-4o access required)
FLASK_SECRET_KEY (random) Secret key for Flask session signing — set a stable value in production
FLASK_DEBUG False Enable Flask debug/hot-reload mode
MAX_UPLOAD_SIZE_MB 10 Maximum CV PDF upload size in megabytes
UPLOAD_FOLDER uploads Directory reserved for upload handling
OUTPUT_FOLDER outputs Directory where generated PDFs and ZIPs are written

Security Notes


Roadmap

The following features are planned for future releases, roughly ordered by priority:

# Feature Description
1 ATS Score & Keyword Report Display a match-score dashboard showing which JD keywords are present/missing in the optimised CV, giving users actionable insight before downloading.
2 Multiple CV Template Styles Offer a choice of professionally designed PDF layouts (e.g. modern, classic, minimal) so users can match the aesthetic expected in their industry.
3 DOCX Export Generate Microsoft Word (.docx) output in addition to PDF, allowing users to make further manual edits using standard word processors.
4 LinkedIn Profile Import Allow users to paste their LinkedIn profile URL as an alternative to uploading a PDF, automatically scraping public profile data as the CV source.
5 Direct Job Board Integration One-click JD import from LinkedIn Jobs, Indeed, and other major job boards via their APIs or structured data, removing the need to copy-paste URLs.
6 Interview Preparation Q&A After generating the optimised CV, produce a set of likely interview questions derived from the JD, with suggested talking points based on the candidate’s experience.
7 Skills Gap Analysis Identify skills listed as required in the JD that are absent from the candidate’s CV, and suggest courses, certifications, or projects to close the gap.
8 Batch Processing Accept a single CV and a list of JDs, producing a full set of tailored documents for each role in one run — ideal for high-volume job searches.
9 User Accounts & Application History Optional account creation to save past optimisation runs, track which roles were applied to, and re-download previously generated documents.
10 Salary Estimation Parse compensation signals from the JD and cross-reference them with market data to provide a realistic salary range for the target role and location.
11 Browser Extension A lightweight browser extension for Chrome/Firefox that adds a one-click “Optimise my CV for this job” button on supported job-board pages.
12 Email Delivery Send the generated PDF bundle directly to the candidate’s inbox after generation, as a convenience alternative to the download buttons.
13 OCR Support for Scanned CVs Integrate an OCR engine (e.g. Tesseract) to extract text from image-based or scanned PDF CVs, removing the current text-PDF-only limitation.
14 Alternative LLM Backends Add support for self-hosted or alternative LLM providers (e.g. Anthropic Claude, Google Gemini, Ollama) so that users are not locked into OpenAI.

License

MIT