Complete ATS-Powered Resume Analysis System
Parse resumes β’ Extract skills β’ Match keywords β’ Calculate ATS scores β’ Generate AI feedback
- β¨ Introduction
- βοΈ Tech Stack
- π Features
- ποΈ System Architecture
- π€Έ Quick Start
- π‘ API Documentation
- π» Usage Examples
- π¨ UI Components
- π§ Configuration
- π Performance
- π Deployment
- π€ Contributing
AI Resume Analyzer is a comprehensive, production-ready system that analyzes resumes against job descriptions using advanced ATS (Applicant Tracking System) algorithms and optional LLM integration. Built with modern web technologies, it provides instant, actionable feedback to help job seekers optimize their resumes.
- π Complete Pipeline: Upload β Parse β Match β Score β Feedback (all in one call)
- π€ LLM Integration: OpenAI GPT-4, Google Gemini, or Anthropic Claude for semantic analysis
- β‘ Lightning Fast: <250ms processing without LLM, ~2-5s with LLM
- π― Smart Matching: 150+ predefined skills with intelligent keyword matching
- π Detailed Scoring: ATS score (0-100) with comprehensive breakdown
- π‘ Actionable Feedback: Categorized suggestions (Critical/Important/Suggestion)
- π¨ Beautiful UI: Modern, responsive design with dark mode support
- π Privacy-First: Memory-only processing, no data persistence
-
React is a popular openβsource JavaScript library for building user interfaces using reusable components and a virtual DOM, enabling efficient, dynamic single-page and native apps.
-
React Router v7 is the goβto routing library for React apps, offering nested routes, data loaders/actions, error boundaries, code splitting, and SSR supportβall with a smooth upgrade path from v6.
-
Puter.com is an advanced, open-source internet operating system designed to be feature-rich, exceptionally fast, and highly extensible. Puter can be used as: A privacy-first personal cloud to keep all your files, apps, and games in one secure place, accessible from anywhere at any time.
-
Puter.js is a tiny clientβside SDK that adds serverless auth, storage, database, and AI (GPT, Claude, DALLΒ·E, OCRβ¦) straight into your browser appβno backend needed and costs borne by users.
-
Tailwind CSS is a utility-first CSS framework that allows developers to design custom user interfaces by applying low-level utility classes directly in HTML, streamlining the design process.
-
TypeScript is a superset of JavaScript that adds static typing, providing better tooling, code quality, and error detection for developers, making it ideal for building large-scale applications.
-
Vite is a fast build tool and dev server using native ES modules for instant startup, hotβmodule replacement, and Rollupβpowered production buildsβperfect for modern web development.
-
Zustand is a minimal, hook-based state management library for React. It lets you manage global state with zero boilerplate, no context providers, and excellent performance through selective state subscriptions.
- β PDF & DOCX Support - Parse both PDF and DOCX resume files
- β Text Extraction - Extract full plain text from documents
- β Field Detection - Automatically detect name, email, phone, skills, education, work experience
- β Metadata Analysis - Calculate word count, text statistics
- β 150+ Predefined Skills - Technical (programming, frameworks, databases, cloud) and soft skills
- β Smart Matching - Exact and partial keyword matching with word boundary detection
- β N-gram Extraction - Capture multi-word skills (e.g., "Machine Learning", "React Native")
- β Text Preprocessing - Lowercase, tokenization, stopword removal
- β Match Analysis - Identify matched vs missing keywords with percentage calculation
- β 0-100 Score - Formula-based scoring: (Matched/Total) Γ 100
- β Format Penalty - Deduct points for poor formatting (0-20 points)
- β Section Completeness - Bonus points for standard sections (0-10 points)
- β Detailed Breakdown - Matched keywords, missing keywords, total keywords
- β Pass/Fail Determination - Configurable threshold (default: 70%)
- β Multi-Provider Support - OpenAI GPT-4, Google Gemini, Anthropic Claude
- β Context-Rich Prompts - Send resume, JD, keywords, ATS score for analysis
- β Structured Feedback - Summary, suggestions, keyword improvements, formatting tips
- β Smart Fallback - Works perfectly without LLM using static feedback
- β Error Handling - Graceful degradation on API failures or timeouts
- β
/api/parse-resume- Parse PDF/DOCX files - β
/api/ats-score- Calculate ATS score and feedback - β
/api/generate-feedback- Generate LLM-powered feedback - β
/api/full-analysis- Complete end-to-end pipeline in one call
- β Modern Design - Clean, responsive interface built with Tailwind CSS
- β Dark Mode - Full theme support
- β Interactive Elements - Color-coded feedback, keyword badges, expandable sections
- β Real-time Results - Instant feedback display
- β Loading States - Smooth transitions and loading indicators
- β Error Handling - User-friendly error messages
- β TypeScript - Full type safety across the entire codebase
- β Modular Architecture - Clean separation of concerns
- β React Hooks - Easy-to-use hooks for API consumption
- β Comprehensive Documentation - Detailed guides and examples
- β
Test Pages - Built-in demo pages for testing (
/test-parser,/test-ats)
Follow these steps to set up the project locally on your machine.
Prerequisites
Make sure you have the following installed on your machine:
Cloning the Repository
git clone https://github.com/your-username/ai-resume-analyzer.git
cd ai-resume-analyzerInstallation
Install the project dependencies:
npm installInstall additional dependencies for resume parsing:
npm install pdf-parse mammoth @types/pdf-parseEnvironment Variables (Optional - for LLM Integration)
Create a .env file in the root directory:
# LLM Configuration (optional - system works without it)
LLM_PROVIDER=openai # Options: openai, gemini, anthropic
LLM_API_KEY=your_api_key_here
LLM_MODEL=gpt-4-turbo-preview
LLM_MAX_TOKENS=1500
LLM_TEMPERATURE=0.7Running the Project
npm run devOpen http://localhost:5173 in your browser to view the project.
Test Pages
- Resume Parser: http://localhost:5173/test-parser
- ATS Scorer: http://localhost:5173/test-ats
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (React) β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Upload Page β β Test Parser β β Test ATS β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Layer (React Router) β
β ββββββββββββββββββββ ββββββββββββββββββββ β
β β /api/parse-resumeβ β /api/ats-score β β
β ββββββββββββββββββββ ββββββββββββββββββββ β
β ββββββββββββββββββββ ββββββββββββββββββββ β
β β /api/generate- β β /api/full- β β
β β feedback β β analysis β β
β ββββββββββββββββββββ ββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Core Libraries (app/lib) β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β βfile-parsers β βskill-extractorβ βskill-matcher β β
β β(PDF/DOCX) β β(150+ skills) β β(matching) β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β βats-scorer β βllm-service β βresume-parser β β
β β(algorithm) β β(OpenAI/etc) β β(fields) β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β External Services (Optional) β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β OpenAI GPT β βGoogle Gemini β βAnthropic β β
β β API β β API β βClaude API β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Upload Resume (PDF/DOCX)
β
2. Parse File β Extract Text
β
3. Extract Skills & Keywords
β
4. Match with Job Description
β
5. Calculate ATS Score
β
6. Generate Feedback (LLM or Static)
β
7. Display Results
Endpoint: POST /api/parse-resume
Content-Type: multipart/form-data
Request:
const formData = new FormData();
formData.append('resume', file); // PDF or DOCX fileResponse:
{
"status": "success",
"text": "Full resume text...",
"fields": {
"name": "John Doe",
"email": "john@example.com",
"phone": "+1234567890",
"skills": ["Python", "React", "AWS"],
"education": [...],
"workExperience": [...]
},
"fileType": "pdf",
"stats": {
"textLength": 2500,
"wordCount": 450
}
}Endpoint: POST /api/ats-score
Content-Type: application/json
Request:
{
"resumeText": "Full resume text...",
"jobDescription": "Job description text...",
"resumeSkills": ["Python", "React"],
"passThreshold": 70
}Response:
{
"atsScore": 75,
"atsPass": true,
"passThreshold": 70,
"scoreBreakdown": {
"matchedKeywords": 8,
"missingKeywords": 3,
"totalKeywords": 11,
"formatPenalty": 5,
"sectionCompleteness": 8
},
"feedback": [
{
"category": "important",
"message": "Missing 3 important keywords.",
"action": "Consider adding: AWS, Docker, Kubernetes."
}
],
"skillMatch": {
"matchedKeywords": ["Python", "React", "Node.js"],
"missingKeywords": ["AWS", "Docker", "Kubernetes"],
"matchPercentage": 73
},
"recommendations": [...]
}Endpoint: POST /api/generate-feedback
Content-Type: application/json
Request:
{
"resumeText": "...",
"jobDescription": "...",
"matchedKeywords": ["Python", "React"],
"missingKeywords": ["AWS", "Docker"],
"atsScore": 75
}Response:
{
"feedback": {
"summary": "Your resume demonstrates strong technical skills...",
"suggestions": ["Add AWS certification...", "..."],
"keywordImprovements": ["Include Docker in DevOps section..."],
"formattingTips": ["Use consistent bullet points..."],
"sectionEnhancements": ["Expand Skills section..."],
"overallRecommendation": "With these improvements...",
"estimatedImpact": "medium"
},
"provider": "openai",
"model": "gpt-4-turbo-preview",
"status": "success"
}Endpoint: POST /api/full-analysis
Content-Type: multipart/form-data
Request:
const formData = new FormData();
formData.append('resume', file);
formData.append('jobDescription', 'Job description text...');
formData.append('jobTitle', 'Software Engineer');
formData.append('useLLM', 'true'); // optionalResponse: Combined results from all steps above
import { useResumeParser } from '~/lib/use-resume-parser';
import { useATSScorer } from '~/lib/use-ats-scorer';
function MyComponent() {
const parser = useResumeParser();
const scorer = useATSScorer();
const handleAnalyze = async (file: File, jobDesc: string) => {
// Step 1: Parse resume
const parsed = await parser.parseResume(file);
if (parsed) {
// Step 2: Calculate ATS score
const score = await scorer.calculateScore({
resumeText: parsed.text,
resumeSkills: parsed.fields.skills,
jobDescription: jobDesc,
});
console.log('ATS Score:', score?.atsScore);
console.log('Matched:', score?.skillMatch.matchedKeywords);
console.log('Missing:', score?.skillMatch.missingKeywords);
}
};
return (
<div>
{/* Your UI */}
</div>
);
}async function analyzeResume(file: File, jobDescription: string) {
const formData = new FormData();
formData.append('resume', file);
formData.append('jobDescription', jobDescription);
formData.append('useLLM', 'true');
const response = await fetch('/api/full-analysis', {
method: 'POST',
body: formData,
});
const result = await response.json();
console.log('ATS Score:', result.atsScoring.atsScore);
console.log('Matched Keywords:', result.skillMatching.matchedKeywords);
console.log('LLM Feedback:', result.llmFeedback?.feedback);
return result;
}Parse Resume:
curl -X POST http://localhost:5173/api/parse-resume \
-F "resume=@resume.pdf"Calculate ATS Score:
curl -X POST http://localhost:5173/api/ats-score \
-H "Content-Type: application/json" \
-d '{
"resumeText": "Software Engineer with Python, React...",
"jobDescription": "Looking for Python, React, AWS..."
}'Full Analysis:
curl -X POST http://localhost:5173/api/full-analysis \
-F "resume=@resume.pdf" \
-F "jobDescription=Looking for Python, React, AWS..." \
-F "useLLM=true"Located at /test-parser, this component demonstrates resume parsing:
- File upload interface
- Parsing progress indicator
- Extracted fields display
- Skills as badges
- Full text viewer
- Error handling
Located at /test-ats, this component demonstrates ATS scoring:
- Side-by-side text input (resume + job description)
- Real-time scoring
- Color-coded results (green/yellow/red based on score)
- Keyword badges (matched in green, missing in red)
- Expandable feedback sections
- Recommendations list
- Score breakdown visualization
OpenAI:
LLM_PROVIDER=openai
LLM_API_KEY=sk-...
LLM_MODEL=gpt-4-turbo-previewGoogle Gemini:
LLM_PROVIDER=gemini
LLM_API_KEY=...
LLM_MODEL=gemini-proAnthropic Claude:
LLM_PROVIDER=anthropic
LLM_API_KEY=...
LLM_MODEL=claude-3-sonnet-20240229Add industry-specific skills:
import { SkillExtractor } from '~/lib/skill-extractor';
const customSkills = ['Rust', 'Elixir', 'Blockchain', 'Web3'];
const extractor = new SkillExtractor(customSkills);Adjust the pass/fail threshold:
import { ATSScorer } from '~/lib/ats-scorer';
const scorer = new ATSScorer(80); // 80% threshold instead of default 70%| Operation | Time | Notes |
|---|---|---|
| PDF Parsing | ~100ms | Typical 2-page resume |
| DOCX Parsing | ~50ms | Faster than PDF |
| Skill Extraction | ~50ms | 150+ skills checked |
| Keyword Matching | ~20ms | Smart comparison |
| ATS Scoring | ~10ms | Formula-based |
| Total (without LLM) | ~230ms | Very fast |
| LLM Feedback | 2-5s | Depends on provider |
| Total (with LLM) | ~2.5-5.5s | Still acceptable |
- Cache parsed resumes to avoid re-parsing
- Batch process multiple resumes
- Use LLM only when needed (fallback is fast)
- Monitor API usage for LLM costs
- Install dependencies:
npm install pdf-parse mammoth - Configure environment variables (if using LLM)
- Test all endpoints locally
- Set up CORS if needed
- Configure rate limiting
- Set up monitoring/logging
- Test with real resumes
- Verify dark mode works
- Test mobile responsiveness
- Set up error tracking (Sentry, etc.)
NODE_ENV=production
LLM_PROVIDER=openai
LLM_API_KEY=your_production_key
LLM_MODEL=gpt-4-turbo-preview
LLM_MAX_TOKENS=1500
LLM_TEMPERATURE=0.7Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow TypeScript best practices
- Add tests for new features
- Update documentation
- Ensure all tests pass
- Follow existing code style
This project is licensed under the MIT License.
- pdf-parse - PDF parsing library
- mammoth - DOCX parsing library
- OpenAI, Google, Anthropic - LLM providers
- React Router - Routing framework
- Tailwind CSS - Styling framework
For questions or issues:
- Open an issue on GitHub
- Check the test pages:
/test-parser,/test-ats - Review API documentation: GET any endpoint for docs
Built with β€οΈ for job seekers everywhere
β Star this repo if you find it helpful!