Production-ready AI resume tailoring platform for ATS scoring, personalized application packages, and candidate application tracking.
Overview • Features • Screenshots • Architecture • Quick Start • API • Deployment • Troubleshooting
AI Resume Intelligence is a full-stack AI platform that helps candidates tailor resumes to job descriptions, estimate ATS alignment, generate application materials, and track role-specific application packages.
It is built as a portfolio-grade AI engineering project with a FastAPI backend, React frontend, Ollama-first local AI workflow, JWT authentication, document parsing, CI/CD checks, Docker support, and production deployment readiness.
|
|
|
|
|
|
| Frontend | Backend API Docs |
|---|---|
| https://resume-api-taranjyot-singh.vercel.app | https://ai-resume-intelligence-3bvb.onrender.com/docs |
flowchart TD
A[React + Vite Frontend] --> B[FastAPI Backend]
B --> C[Auth API]
B --> D[Document Extraction API]
B --> E[Candidate + Job API]
B --> F[AI Tailoring API]
B --> G[Application Logs API]
F --> H[AI Provider Router]
H --> I[Ollama Provider]
H --> J[Cloud Provider Stub]
B --> K[(SQLite Local DB)]
B --> L[(PostgreSQL Production DB)]
D --> M[PDF / DOCX / TXT Parser]
F --> N[ATS Scoring Engine]
F --> O[Tailored Package Generator]
User Opens Landing Page
↓
User Continues as Guest or Logs in as Candidate
↓
User Uploads/Pastes Resume and Job Description
↓
Backend Extracts Text and Creates Candidate/Job Context
↓
ATS Scoring Engine Calculates Current Alignment
↓
AI Provider Generates Resume, Cover Letter, Email, LinkedIn Message, and Interview Prep
↓
Frontend Displays Tailored Package with Runtime
↓
Registered Candidate Gets an Automatic Application Log
↓
User Reviews, Views, or Edits Application Tracker Entries
| Step | What Happens |
|---|---|
| 1 | React frontend collects resume and job description content |
| 2 | FastAPI parses uploaded files or accepts pasted text |
| 3 | Candidate/job records are created internally for analysis |
| 4 | ATS scoring compares resume keywords against the target JD |
| 5 | AI provider generates role-aware application materials |
| 6 | Registered users receive an auto-created application log |
| 7 | Application logs store resume, JD, and tailored package summary |
📁 Folder Structure
resume-ai-platform/
├── .github/
│ └── workflows/ # GitHub Actions CI checks
├── backend/
│ ├── app/
│ │ ├── api/ # Auth, candidate, job, document, AI, application routes
│ │ ├── core/ # Config, DB setup, security helpers
│ │ ├── models/ # SQLAlchemy entities
│ │ ├── providers/ # Ollama and cloud provider abstractions
│ │ ├── schemas/ # Pydantic request/response DTOs
│ │ └── services/ # Parsing, scoring, prompt, AI routing logic
│ ├── tests/ # API, parser, scoring, and health tests
│ ├── Dockerfile
│ ├── requirements.txt
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── main.jsx # React app logic
│ │ └── style.css # Responsive UI styling
│ ├── Dockerfile
│ ├── package.json
│ └── vercel.json
├── infra/
│ └── jenkins/
│ └── Jenkinsfile # Jenkins pipeline definition
├── postman/
│ └── Resume-AI-Platform.postman_collection.json
├── docs/
│ └── screenshots/
├── docker-compose.yml
└── README.md
| Requirement | Version |
|---|---|
| Python | 3.11+ / 3.12 recommended |
| Node.js | 20.19+ or 22.12+ |
| Ollama | Local model runtime |
| Docker | Optional |
| Git | Any recent version |
Ollama may already be running in the background.
ollama listPull the required local models:
ollama pull llama3.1:8b
ollama pull nomic-embed-textStart Ollama if needed:
ollama serveIf you see this message:
bind: Only one usage of each socket address...
Ollama is already running on port 11434.
Verify the local API:
curl http://localhost:11434/api/tagsTest generation:
curl http://localhost:11434/api/generate \
-d '{"model":"llama3.1:8b","prompt":"Say hello in one sentence","stream":false}'cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Windows PowerShell:
cd backend
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Open:
http://localhost:8000/docs
cd frontend
npm install
npm run devOpen:
http://localhost:5173
For LAN/mobile testing, open the app using your local IP:
http://192.168.1.x:5173
APP_NAME=Resume AI Platform
ENVIRONMENT=local
DATABASE_URL=sqlite:///./resume_ai.db
REDIS_URL=redis://localhost:6379/0
JWT_SECRET=auto-generate-for-local-dev
JWT_ALGORITHM=HS256
OLLAMA_BASE_URL=http://localhost:11434
DEFAULT_AI_PROVIDER=ollama
DEFAULT_GENERATION_MODEL=llama3.1:8b
DEFAULT_EMBEDDING_MODEL=nomic-embed-text
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,http://localhost:3000For local development, create frontend/.env:
VITE_API_URL=http://localhost:8000/api/v1For Vercel, set this variable directly in the Vercel dashboard:
VITE_API_URL=https://your-render-backend-url.onrender.com/api/v1For local development, the backend can create backend/.env if it is missing and replace placeholder JWT values such as:
JWT_SECRET=auto-generate-for-local-dev
JWT_SECRET=replace-this-with-a-long-random-secret
JWT_SECRET=change-me-in-productionwith a strong generated secret.
Existing real secrets are not overwritten.
For production, set JWT_SECRET through the deployment platform:
- Render environment variables
- Docker/Kubernetes secrets
- AWS Secrets Manager
- Vault
- CI/CD secret stores
cd backend
pytest --cov=app --cov-report=term-missing
ruff check app tests
bandit -r app -llCurrent backend coverage areas:
| Area | Coverage |
|---|---|
| Health checks | API startup and readiness |
| Auth flow | Register/login/JWT behavior |
| Candidate APIs | Candidate profile creation |
| Job APIs | Job description creation |
| Document parser | PDF/DOCX/TXT extraction |
| ATS scoring | Keyword and projected score logic |
| Application logs | Auto-created logs and edits |
Frontend checks:
cd frontend
npm install
npm run build
npm run lintcurl http://localhost:8000/healthcurl -X POST http://localhost:8000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"demo","email":"demo@example.com","password":"qwerty"}'curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"identifier":"demo","password":"qwerty"}'curl -X POST http://localhost:8000/api/v1/candidates \
-H "Content-Type: application/json" \
-d '{"full_name":"Demo Candidate","target_role":"Python Developer","location":"Canada","resume_text":"Python FastAPI AWS Docker SQL","skills":"Python, FastAPI"}'curl -X POST http://localhost:8000/api/v1/jobs \
-H "Content-Type: application/json" \
-d '{"company":"DemoCo","title":"Backend Developer","description":"Python FastAPI AWS SQL Docker APIs"}'curl -X POST http://localhost:8000/api/v1/documents/extract-text \
-F "file=@resume.pdf"curl -X POST http://localhost:8000/api/v1/ai/tailor \
-H "Content-Type: application/json" \
-d '{"candidate_id":1,"job_id":1,"provider":"ollama","model":"llama3.1:8b"}'Import:
postman/Resume-AI-Platform.postman_collection.json
Set collection variable:
baseUrl = http://localhost:8000
Use Postman to test:
- Auth register/login
- Candidate creation
- Job creation
- Document upload/extraction
- Tailored package generation
- Application log retrieval and update
docker compose up --buildWhen running directly on the host:
OLLAMA_BASE_URL=http://localhost:11434When running inside Docker, the backend may need host networking configuration depending on your OS:
OLLAMA_BASE_URL=http://host.docker.internal:11434|
Recommended service type:
Production variables: ENVIRONMENT=production
DATABASE_URL=<production-db-url>
JWT_SECRET=<secure-secret>
JWT_ALGORITHM=HS256
CORS_ORIGINS=<vercel-frontend-url>
DEFAULT_AI_PROVIDER=ollama
DEFAULT_GENERATION_MODEL=llama3.1:8b
DEFAULT_EMBEDDING_MODEL=nomic-embed-text |
Recommended settings:
Production variable: VITE_API_URL=https://your-render-backend-url.onrender.com/api/v1After changing variables, redeploy the frontend. |
|
Pytest validates health routes, parsing, scoring, API flows, and application logs. |
Ruff checks code style and catches Python issues before deployment. |
Bandit scans backend code for common Python security risks. |
Vite build verifies the React app compiles for production. |
Render and Vercel can auto-deploy after successful pushes. |
The GitHub Actions workflow runs on pushes and pull requests.
Typical checks:
Backend Tests, Lint, Security
Frontend Build and Lint
The Jenkinsfile is located at:
infra/jenkins/Jenkinsfile
Pipeline stages:
- Backend install
- Backend lint using Ruff
- Backend security scan using Bandit
- Backend tests using Pytest
- Frontend install/build
To run Jenkins automatically on GitHub pushes:
- Create a Jenkins Pipeline or Multibranch Pipeline job.
- Connect it to the GitHub repository.
- Set script path:
infra/jenkins/Jenkinsfile
- Configure a GitHub webhook pointing to Jenkins.
- Add required Jenkins credentials and tools:
- Python 3.11+
- Node 20.19+ or 22.12+
- npm
| Skill Area | Demonstrated Through |
|---|---|
| Backend Engineering | FastAPI APIs, route separation, typed request/response schemas |
| AI Engineering | Ollama integration, provider abstraction, prompt orchestration |
| Full-Stack Development | React workspace connected to authenticated FastAPI services |
| Authentication | JWT auth, username/email login, session persistence |
| Document Processing | PDF/DOCX/TXT extraction and normalization |
| Scoring Logic | ATS score, projected score, keyword matching |
| Product Thinking | Guest mode, candidate mode, application logs, mobile-ready UI |
| DevOps | GitHub Actions, Jenkins, Docker, Render, Vercel |
| Security | JWT secrets, CORS configuration, Bandit checks |
| Production Readiness | Environment config, deployment docs, troubleshooting, CI gates |
Ollama says port 11434 is already in use
This usually means Ollama is already running.
Verify:
curl http://localhost:11434/api/tags
ollama psIf models appear, Ollama is working.
AI provider unavailable
Check that Ollama is running and the generation model exists:
ollama list
ollama pull llama3.1:8b
curl http://localhost:11434/api/tagsAlso verify:
OLLAMA_BASE_URL=http://localhost:11434
DEFAULT_GENERATION_MODEL=llama3.1:8bRegister/login fails with password longer than 72 bytes
Bcrypt only supports passwords up to 72 bytes.
The backend should validate or truncate safely before hashing. Use normal-length passwords during local testing and avoid accidentally passing large strings into the password field.
Frontend shows Failed to fetch
Common causes:
- Frontend is still pointing to localhost.
- Vercel variable is named incorrectly.
- Backend CORS does not include the Vercel URL.
- Backend deployment is sleeping or cold-starting.
- Frontend was not redeployed after environment variable changes.
Verify frontend variable:
VITE_API_URL=https://your-render-backend-url.onrender.com/api/v1Verify backend CORS:
CORS_ORIGINS=https://your-vercel-frontend-url.vercel.appRender build fails with pydantic-core / maturin / Rust errors
Use a supported Python runtime and pinned dependencies.
Recommended:
Python 3.12
Add or keep:
.python-version
with:
3.12
Then redeploy.
Render fails with email-validator is not installed
Install the missing dependency:
pip install email-validatorOr add it to backend/requirements.txt:
email-validatorThen commit and redeploy.
Ruff reports E741 ambiguous variable name
Avoid single-letter names like l.
Use:
lines = [
line.strip()
for line in resume.splitlines()
if len(line.strip()) > 20
]GitHub Actions cannot import app
Run backend tests from the backend directory or set PYTHONPATH.
Example:
working-directory: backend
env:
PYTHONPATH: .Vercel still calls localhost after deployment
Make sure the frontend code uses:
const API = import.meta.env.VITE_API_URL || 'http://localhost:8000/api/v1';Then set VITE_API_URL in Vercel and redeploy.
cd backend
rm -rf .venv
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
ruff check app tests
pytest
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000cd frontend
rm -rf node_modules dist
npm install
npm run build
npm run dev| Priority | Improvement |
|---|---|
| High | PostgreSQL production migration and persistent storage |
| High | Cloud LLM provider implementations for OpenAI, Claude, Gemini, Azure OpenAI, and Bedrock |
| High | Resume export to DOCX/PDF |
| Medium | User profile settings and multiple resumes per candidate |
| Medium | Application status analytics dashboard |
| Medium | S3-based document storage |
| Medium | Admin dashboard for usage metrics |
| Low | Kubernetes deployment manifests |
| Low | Terraform infrastructure templates |
| Low | Observability dashboards with Prometheus/Grafana |
This project is licensed under the MIT License.
This project is intended for educational, portfolio, and productivity use.
AI-generated resumes, cover letters, and outreach messages should be reviewed by the user before submission. ATS scores are heuristic estimates and should not be treated as guarantees of interview selection.



