AI-powered resume analysis that helps you beat the bots.
Features • Tech Stack • Architecture • Getting Started • API
ATS Resume Analyzer is a full-stack web application that helps job seekers optimize their resumes for Applicant Tracking Systems (ATS). Upload your resume as a PDF, paste any job description, and get:
- A compatibility score visualized as an animated circular ring
- A skill gap analysis — color-coded chips for matching, missing, and extra skills
- AI-powered suggestions via Google Gemini to improve bullet points and formatting
- ATS optimization tips tailored to your specific resume and target role
Built with a React frontend (dark glassmorphism UI), a secure Express API, MongoDB for persistence, and Google's Gemini 2.0 Flash model for intelligent analysis.
| Feature | Description |
|---|---|
| 🔐 JWT Authentication | Secure register / login with bcrypt-hashed passwords and stateless JWT sessions |
| 🛡️ Auth Guard | Unauthenticated users are automatically redirected to /login |
| 🚪 Logout | One-click logout that clears the session token |
| 📄 Drag & Drop Upload | Drag your PDF onto the upload zone or click to browse |
| ✍️ Custom Job Description | Paste any job description into the textarea — no more hardcoded demo JD |
| 🎯 ATS Scoring | Calculates a keyword-match score between your resume and the job description |
| 📊 Score Ring | Compatibility score displayed as an animated SVG circular progress ring |
| 🏷️ Skill Chips | Skills rendered as color-coded pill badges — green ✅ matching, red ❌ missing, yellow 🟡 extra |
| 🤖 AI Analysis | Google Gemini generates structured feedback: missing skills, bullet improvements, and overall assessment |
| 🎨 Premium Dark UI | Glassmorphism cards, Inter font, gradient buttons, fade-in modal, hover micro-animations |
| 📱 Responsive Design | Fully mobile-friendly layout |
| ⚡ Zero Config Dev | Webpack dev server with built-in API proxy — no CORS headaches |
- React 18 — UI library
- React Router DOM v6 — Client-side routing (
/login,/register,/) - Webpack 5 — Module bundler with
DefinePluginfor env variable injection - Babel — JSX / ES6+ transpilation
- CSS3 — Component-scoped styles with glassmorphism, animations (no external UI framework)
- Inter — Google Font for modern typography
- Node.js + Express 4 — REST API server
- MongoDB + Mongoose 8 — User data persistence
- Multer — In-memory file upload handling
- pdfjs-dist — Server-side PDF text extraction
- jsonwebtoken + bcrypt — Auth layer
- Google Gemini API — Generative AI for resume analysis (gemini-2.0-flash-exp)
ATS-Analyzer/
├── client/ # React SPA
│ ├── components/
│ │ ├── Login/ # Auth screen (dark glassmorphism)
│ │ ├── Register/ # Sign-up screen (dark glassmorphism)
│ │ └── YourResumes/ # Upload + analysis dashboard
│ ├── App.jsx # Router setup with auth guard
│ ├── main.jsx # React 18 createRoot entry
│ ├── index.html # HTML template + Inter font
│ ├── .env # Client env vars (not committed)
│ └── webpack.config.js # Dev + build config with API proxy + DefinePlugin
│
└── server/ # Express API
├── controllers/
│ ├── authController.js # Register / Login handlers
│ └── resumeController.js # Upload + analyze handlers
├── middleware/
│ ├── authMiddleware.js # JWT verification guard
│ └── upload.js # Multer memoryStorage config
├── models/
│ └── user.js # Mongoose User schema
├── routes/
│ ├── authRoutes.js # POST /auth/register, /auth/login
│ └── resumeRoutes.js # POST /resume/upload, /resume/analyze
├── utils/
│ ├── resumeParser.js # PDF → text (pdfjs-dist)
│ ├── keywordExtractor.js # Regex tokenization
│ ├── atsScore.js # Jaccard-style keyword match %
│ └── aiAnalyzer.js # Gemini API prompt + response parsing
├── .env.example # Required env vars template
└── server.js # Express app bootstrap + DB connection
- Node.js ≥ 18
- MongoDB running locally (or a MongoDB Atlas URI)
- Google Gemini API Key — Get one free
git clone https://github.com/Avila-Princy-M01/ATS-Analyzer.git
cd ATS-Analyzer
npm installcp server/.env.example server/.envEdit server/.env:
MONGO_URI=mongodb://localhost:27017/ats-analyser
JWT_SECRET=replace_with_a_long_random_string
GEMINI_API_KEY=your_gemini_api_key_hereImportant MongoDB Atlas Note: If you are using a cloud MongoDB Atlas URI, ensure your local machine's IP address (or
0.0.0.0/0for development) is added to the Network Access IP Access List in the Atlas dashboard. Otherwise, the backend server will throw aMongooseServerSelectionErroron startup.
Create client/.env:
REACT_APP_API_URL=http://localhost:5000Note: This file is gitignored and must be created manually after cloning. Webpack reads it at build time via
DefinePlugin.
Terminal 1 — Backend:
npm run server:dev
# Server running on port 5000Terminal 2 — Frontend:
npm run client
# Webpack dev server on port 3000The React dev server proxies /auth and /resume requests to http://localhost:5000 automatically, so everything just works.
npm run client:build
# Outputs to client/dist/| Method | Endpoint | Body | Response |
|---|---|---|---|
POST |
/auth/register |
{ name, email, password } |
{ message: "Registered successfully" } |
POST |
/auth/login |
{ email, password } |
{ token: "<jwt>" } |
| Method | Endpoint | Body / FormData | Response |
|---|---|---|---|
POST |
/resume/upload |
FormData with resume (PDF file) |
{ success, preview, text } |
POST |
/resume/analyze |
{ resumeText, jobDescription } |
{ success, score, suggestions } |
The AI returns a structured JSON object:
{
"analysis": {
"resume_skills": ["react", "node.js", "mongodb"],
"job_description_skills": ["react", "typescript", "aws"],
"missing_skills": {
"from_resume_for_job_description": ["typescript", "aws"],
"from_job_description_for_resume": []
},
"ats_optimized_bullet_point_improvements": [
{
"original_summary": "Built a website",
"suggested_bullets": [
"Developed a responsive React frontend serving 10,000+ monthly users"
],
"reasoning": "Quantified impact and specified technology stack"
}
],
"ats_optimization_tips": ["Add a Skills section", "Use standard job titles"],
"compatibility_score": 65,
"overall_assessment": "Strong frontend background..."
}
}- Upload — User drags & drops or selects a PDF resume. Multer buffers it in memory.
- Parse —
pdfjs-distextracts plain text from every page of the PDF. - Analyze (local) —
keywordExtractor.jstokenizes both the resume and the user-provided job description.atsScore.jscomputes a keyword overlap percentage. - Analyze (AI) — The full resume text + job description are sent to Google Gemini 2.0 Flash with a strict JSON-structured prompt.
- Report — The frontend renders a modal with an animated score ring, color-coded skill chips, bullet rewrites, and actionable tips.
| Variable | Required | Description |
|---|---|---|
MONGO_URI |
✅ | MongoDB connection string |
JWT_SECRET |
✅ | Secret for signing JWTs |
GEMINI_API_KEY |
✅ | Google AI Studio API key |
| Variable | Required | Description |
|---|---|---|
REACT_APP_API_URL |
✅ | Base URL of the backend API (e.g. http://localhost:5000) |
npm run server # Start production server
npm run server:dev # Start server with --watch (Node 18+)
npm run client # Start webpack dev server (port 3000)
npm run client:build # Production build (client/dist/)- Support
.docxresume uploads -
Dynamic job description input— users can now paste any JD - Persistent analysis history per user
- Resume storage in MongoDB GridFS
- Enhanced keyword extraction with NLP (spaCy / natural)
-
Dark mode toggle— dark theme applied globally
MIT — feel free to fork, adapt, and improve.
Built with ☕ + React + Node + Gemini