Skip to content

laharikarrotu/ats_resume_app

Repository files navigation

ATS Resume Generator πŸš€

Full-Stack AI-Powered Resume Optimization Tool
Built with FastAPI, LLM (OpenAI/Gemini), Vector Search, and Modern Web Stack


🎯 Project Overview

This is a production-ready, recruiter-impressive ATS (Applicant Tracking System) resume generator that:

  • Extracts job-specific keywords from job descriptions using LLMs (OpenAI/Gemini)
  • Generates ATS-optimized resumes in Word (.docx) format with intelligent keyword injection
  • Provides a modern web UI for recruiters and job seekers
  • Uses vector embeddings to match candidate experience with job requirements (RAG)
  • Maintains 1-page C3 resume format for maximum ATS compatibility

Perfect for showcasing: Full-Stack Development, ML/LLM Engineering, and Production-Ready Software Architecture.


πŸ—οΈ Architecture

System Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Client Layer                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Web Browser β”‚  β”‚   Mobile UI  β”‚  β”‚   API Client        β”‚  β”‚
β”‚  β”‚  (HTML/JS)   β”‚  β”‚   (Future)   β”‚  β”‚   (cURL/Postman)    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                  β”‚                      β”‚
          β”‚  HTTP/REST       β”‚                      β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    FastAPI Application Layer                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  FastAPI Server (Uvicorn)                                β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚   Routes    β”‚  β”‚   Middleware β”‚  β”‚   Auth/JWT   β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  /generate  β”‚  β”‚   (CORS,     β”‚  β”‚   (Future)   β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  /download  β”‚  β”‚    Logging)  β”‚  β”‚              β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  /health    β”‚  β”‚              β”‚  β”‚              β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                 β”‚                  β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”      β”‚
β”‚    β”‚   Business    β”‚  β”‚   LLM Client β”‚  β”‚   Vector    β”‚      β”‚
β”‚    β”‚   Logic       β”‚  β”‚   (OpenAI/   β”‚  β”‚   Search    β”‚      β”‚
β”‚    β”‚   Layer       β”‚  β”‚   Gemini)    β”‚  β”‚   (RAG)     β”‚      β”‚
β”‚    β”‚               β”‚  β”‚              β”‚  β”‚             β”‚      β”‚
β”‚    β”‚  β€’ Resume     β”‚  β”‚  β€’ Keyword   β”‚  β”‚  β€’ Embed    β”‚      β”‚
β”‚    β”‚    Generator  β”‚  β”‚    Extract   β”‚  β”‚    JD       β”‚      β”‚
β”‚    β”‚  β€’ Template   β”‚  β”‚  β€’ Bullet    β”‚  β”‚  β€’ Match    β”‚      β”‚
β”‚    β”‚    Engine     β”‚  β”‚    Rewrite   β”‚  β”‚    Exp.     β”‚      β”‚
β”‚    β”‚  β€’ Formatting β”‚  β”‚  β€’ STAR      β”‚  β”‚  β€’ Retrieve β”‚      β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚            β”‚                  β”‚                 β”‚             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”     β”‚
β”‚    β”‚   Data Layer   β”‚  β”‚   Storage   β”‚  β”‚   External  β”‚     β”‚
β”‚    β”‚                β”‚  β”‚             β”‚  β”‚   Services  β”‚     β”‚
β”‚    β”‚  β€’ PostgreSQL  β”‚  β”‚  β€’ Vector   β”‚  β”‚             β”‚     β”‚
β”‚    β”‚    (Future)    β”‚  β”‚    DB       β”‚  β”‚  β€’ OpenAI   β”‚     β”‚
β”‚    β”‚  β€’ Pydantic    β”‚  β”‚    (Chroma/ β”‚  β”‚    API      β”‚     β”‚
β”‚    β”‚    Models      β”‚  β”‚    Qdrant)  β”‚  β”‚  β€’ Gemini   β”‚     β”‚
β”‚    β”‚  β€’ File System β”‚  β”‚             β”‚  β”‚    API      β”‚     β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ Data Flow

Resume Generation Flowchart

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    USER INPUT                                 β”‚
β”‚  1. Paste Job Description (JD)                                β”‚
β”‚  2. Optionally: Upload existing resume / experience data      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              STEP 1: JOB DESCRIPTION PROCESSING               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  β€’ Validate JD format (Pydantic)                      β”‚   β”‚
β”‚  β”‚  β€’ Preprocess text (clean, normalize)                 β”‚   β”‚
β”‚  β”‚  β€’ Extract metadata (title, company, location)        β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          STEP 2: LLM KEYWORD EXTRACTION                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  OpenAI/Gemini API Call:                              β”‚   β”‚
β”‚  β”‚  β€’ Prompt: "Extract 20-40 skills/keywords from JD"   β”‚   β”‚
β”‚  β”‚  β€’ Model: gpt-4o-mini / gemini-pro                   β”‚   β”‚
β”‚  β”‚  β€’ Output: JSON array of keywords                     β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        STEP 3: VECTOR SEARCH (RAG) - OPTIONAL                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  IF user has uploaded experience data:                β”‚   β”‚
β”‚  β”‚  β€’ Embed JD keywords using sentence-transformers      β”‚   β”‚
β”‚  β”‚  β€’ Query vector DB for matching experience bullets    β”‚   β”‚
β”‚  β”‚  β€’ Retrieve top 5-10 most relevant experience items   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          STEP 4: RESUME GENERATION                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  β€’ Load template (c3_template.docx) or create new     β”‚   β”‚
β”‚  β”‚  β€’ Inject keywords into "Key Skills" section          β”‚   β”‚
β”‚  β”‚  β€’ Format with python-docx (1-page limit)            β”‚   β”‚
β”‚  β”‚  β€’ Apply ATS-friendly formatting                      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              STEP 5: OUTPUT                                   β”‚
β”‚  β€’ Save DOCX to outputs/ directory                           β”‚
β”‚  β€’ Return file download link or direct file response         β”‚
β”‚  β€’ Log generation metadata (for analytics)                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Tech Stack

Core Stack

Layer Technology Purpose
Web Framework FastAPI High-performance async API + auto-generated docs
LLM Provider OpenAI / Google Gemini Keyword extraction, bullet rewriting, STAR formatting
Document Generation python-docx Word (.docx) resume creation with precise formatting
Vector Search sentence-transformers + Chroma/Qdrant RAG for matching experience with job requirements
Validation Pydantic v2 Type-safe API request/response validation
Templating Jinja2 Dynamic HTML generation for web UI

Frontend Stack (Future)

Technology Purpose
HTML5 + Tailwind CSS Modern, responsive web UI
Vanilla JS / Alpine.js Lightweight interactivity (no heavy frameworks)
Fetch API Async API calls to FastAPI backend

Infrastructure & DevOps

Technology Purpose
Docker Containerization for portable deployment
Docker Compose Multi-service orchestration (app + DB + vector DB)
GitHub Actions CI/CD pipeline (tests β†’ build β†’ deploy)
PostgreSQL (Future) Persistent storage for user accounts, job history
Prometheus / Grafana (Future) Metrics and observability

ML/LLM Stack

Technology Purpose
OpenAI API GPT-4o-mini for cost-effective keyword extraction
sentence-transformers Generate embeddings for JD and experience bullets
Chroma / Qdrant Vector database for semantic search

πŸ“ Project Structure

ats_resume_app/
β”‚
β”œβ”€β”€ README.md                      # This file
β”œβ”€β”€ requirements.txt               # Python dependencies
β”œβ”€β”€ .gitignore                     # Git ignore rules
β”œβ”€β”€ Dockerfile                     # Docker container config
β”œβ”€β”€ docker-compose.yml             # Multi-service orchestration (Future)
β”‚
β”œβ”€β”€ resume_templates/              # Word template files
β”‚   └── c3_template.docx           # C3 format resume template
β”‚
β”œβ”€β”€ outputs/                       # Generated resumes (gitignored)
β”‚   └── .gitkeep
β”‚
β”œβ”€β”€ src/                           # Application source code
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ main.py                    # FastAPI app entry point
β”‚   β”œβ”€β”€ models.py                  # Pydantic models for validation
β”‚   β”œβ”€β”€ resume_generator.py        # Core Word generation logic
β”‚   β”œβ”€β”€ llm_client.py              # OpenAI/Gemini API integration
β”‚   β”œβ”€β”€ vector_search.py           # RAG/vector search (Future)
β”‚   └── utils.py                   # Helper functions
β”‚
β”œβ”€β”€ static/                        # Static assets
β”‚   └── styles.css                 # CSS styles
β”‚
β”œβ”€β”€ templates/                     # HTML templates
β”‚   └── index.html                 # Main web UI
β”‚
β”œβ”€β”€ tests/                         # Test suite (Future)
β”‚   β”œβ”€β”€ test_resume_generator.py
β”‚   β”œβ”€β”€ test_llm_client.py
β”‚   └── conftest.py
β”‚
└── .github/                       # CI/CD workflows
    └── workflows/
        └── ci.yml                 # GitHub Actions pipeline

πŸš€ Quick Start

Prerequisites

  • Python 3.11+
  • pip
  • (Optional) Docker + Docker Compose

Local Development

  1. Clone and navigate to the project:
cd ats_resume_app
  1. Create a virtual environment:
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
  1. Install dependencies:
pip install -r requirements.txt
  1. Set environment variables:
# On Windows PowerShell:
$env:OPENAI_API_KEY = "sk-your-key-here"

# On Linux/Mac:
export OPENAI_API_KEY="sk-your-key-here"
  1. Run the application:
uvicorn src.main:app --reload
  1. Open in browser:

Docker Deployment

# Build image
docker build -t ats-resume-app .

# Run container
docker run -p 8000:8000 -e OPENAI_API_KEY=sk-your-key ats-resume-app

Cloud Deployment

This app can be deployed to various platforms:

  • Railway (Recommended) - Best for FastAPI apps
  • Render - Easy deployment with auto-scaling
  • Vercel - Serverless functions (limited for long-running tasks)
  • Fly.io - Global distribution

Quick Deploy to Railway:

  1. Push code to GitHub
  2. Go to https://railway.app and sign up with GitHub
  3. Create new project β†’ Deploy from GitHub repo
  4. Add OPENAI_API_KEY environment variable in Variables tab
  5. Railway auto-deploys! Get your URL from Settings β†’ Domains

Detailed Railway Setup:

  • Connect your GitHub repository to Railway
  • Railway automatically detects FastAPI and deploys
  • Add environment variables in the Variables tab
  • Your app will be live at https://your-app.up.railway.app

πŸ“Š API Endpoints

Web UI

  • GET / - Main HTML interface

API Endpoints

  • POST /generate_resume/ - Generate resume from form data (returns DOCX file)
  • POST /api/generate_resume - Generate resume from JSON (returns metadata + download link)
  • GET /download/{filename} - Download generated resume
  • GET /health - Health check endpoint
  • GET /docs - Interactive API documentation (Swagger UI)

Example API Usage

# JSON API
curl -X POST "http://localhost:8000/api/generate_resume" \
  -H "Content-Type: application/json" \
  -d '{
    "job_description": "Looking for a Python developer with FastAPI experience..."
  }'

🎯 Roadmap & Features

βœ… Phase 1: Core MVP (Current)

  • Basic FastAPI server
  • LLM keyword extraction (placeholder)
  • DOCX resume generation
  • Simple web UI
  • Docker support

πŸ”„ Phase 2: Production-Ready (Next Steps)

  • OpenAI Integration - Real LLM keyword extraction
  • Enhanced Resume Generation - Better formatting, STAR bullets
  • Vector Search (RAG) - Match experience with job requirements
  • PostgreSQL Database - User accounts, job history
  • JWT Authentication - Secure multi-user access
  • Logging & Metrics - Structured logging, Prometheus metrics

πŸš€ Phase 3: Advanced Features

  • Multiple Resume Templates - Choose from C3, modern, creative
  • Batch Processing - Generate resumes for multiple job descriptions
  • Resume Analytics - ATS score, keyword match percentage
  • CI/CD Pipeline - Automated testing and deployment
  • Cloud Deployment - Deploy to AWS/GCP/Azure

πŸ§ͺ Testing

# Run tests (when implemented)
pytest tests/

# With coverage
pytest --cov=src tests/

πŸ“ Environment Variables

Variable Description Required
OPENAI_API_KEY OpenAI API key for LLM features Yes (for production)
GEMINI_API_KEY Google Gemini API key (alternative) Optional
DATABASE_URL PostgreSQL connection string (future) No
JWT_SECRET Secret key for JWT auth (future) No

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License.


πŸ™ Acknowledgments


πŸ“ž Contact & Support

For questions, issues, or suggestions, please open an issue on GitHub.


Built with ❀️ for Full-Stack and ML/LLM Engineers