A complete MERN stack application that uses Google's Gemini AI to transform resumes into ATS-friendly, optimized documents. Upload PDF or DOCX files, get AI-powered enhancements, and download professionally formatted resumes that pass Applicant Tracking Systems.
- Smart Upload & Parsing: Upload PDF/DOCX resumes and automatically extract structured data using AI
- AI Enhancement: Gemini-powered content optimization with action verbs, metrics, and ATS keywords
- Rich Text Editor: Edit resume sections with TipTap WYSIWYG editor
- ATS-Friendly Templates: Single-column, text-based PDF output optimized for ATS parsing
- Drag & Reorder: Reorganize experience, education, and project sections
- User Authentication: JWT-based auth to save and manage multiple resumes
- Live Preview: Real-time preview of resume with PDF export functionality
- Responsive Design: Built with TailwindCSS for mobile and desktop
- Node.js + Express: REST API server
- MongoDB + Mongoose: Database and ODM
- Gemini AI API: AI parsing and content enhancement
- Multer: File upload handling
- pdf-parse: PDF text extraction
- mammoth: DOCX text extraction
- JWT: Authentication
- bcryptjs: Password hashing
- React 18 + Vite: Modern React with fast HMR
- TailwindCSS: Utility-first CSS framework
- TipTap: Rich text editor for resume content
- React Router: Client-side routing
- React Dropzone: Drag-and-drop file uploads
- react-to-print: Text-based PDF generation
- Axios: HTTP client
- Node.js 18+ and npm/yarn
- MongoDB Atlas account (or local MongoDB)
- Google Gemini API Key (Get one here)
cd ATS_RESUME_GENERATORcd server
npm install
# Copy environment template
cp .env.example .env
# Edit .env with your credentials
nano .envConfigure .env:
PORT=5000
NODE_ENV=development
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/ats_resume
GEMINI_API_KEY=your_gemini_api_key_here
JWT_SECRET=your_super_secret_jwt_key_change_this
CLIENT_ORIGIN=http://localhost:5173Start the server:
npm run devServer runs on http://localhost:5000
cd ../client
npm install
# Start development server
npm run devClient runs on http://localhost:5173
http://localhost:5000/api
POST /api/auth/register
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123"
}POST /api/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "password123"
}
# Response includes JWT token
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "...", "email": "...", "name": "..." }
}GET /api/auth/me
Authorization: Bearer <token>POST /api/resume/upload
Content-Type: multipart/form-data
# Upload file with field name 'resume'
curl -X POST http://localhost:5000/api/resume/upload \
-F "resume=@/path/to/resume.pdf"Response:
{
"message": "Resume uploaded and parsed successfully",
"data": {
"name": "John Doe",
"contact": { "email": "john@example.com", ... },
"summary": "Experienced software engineer...",
"skills": [...],
"experience": [...],
"education": [...],
"rawText": "..."
}
}POST /api/resume/enhance
Content-Type: application/json
{
"content": ["Worked on backend systems", "Fixed bugs"],
"sectionType": "experience"
}Response:
{
"message": "Content enhanced successfully",
"enhanced": [
"Architected and implemented scalable backend systems serving 10K+ users",
"Resolved critical production bugs, improving system stability by 40%"
]
}POST /api/resume/generate-summary
Content-Type: application/json
{
"resumeData": { ... }
}POST /api/resume/save
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "John Doe",
"contact": { ... },
"summary": "...",
...
}PUT /api/resume/:id
Authorization: Bearer <token>
Content-Type: application/jsonGET /api/resume/list
Authorization: Bearer <token>GET /api/resume/:id
Authorization: Bearer <token>DELETE /api/resume/:id
Authorization: Bearer <token>-
Upload Flow
- Navigate to
/upload - Drag and drop a PDF resume
- Verify file upload shows loading state
- Confirm redirect to
/editorwith parsed data - Check all sections populated correctly
- Navigate to
-
Editor Flow
- Edit personal information fields
- Modify summary text
- Add/remove skills categories
- Edit experience bullets using TipTap
- Click "Enhance" on experience section
- Verify AI-enhanced content appears
- Reorder experience items (up/down arrows)
- Add new project/education entries
-
Preview & Export
- Click "Show Preview"
- Verify resume renders correctly
- Check ATS-friendly formatting (single column, clear sections)
- Click "Download PDF"
- Open PDF and verify text is selectable (not image)
- Copy text from PDF to confirm ATS can parse
-
Authentication
- Register new account at
/register - Login at
/login - Click "Save Resume" in editor
- Navigate to
/dashboard - Verify saved resume appears
- Click "Open" to load resume
- Delete a resume and confirm removal
- Register new account at
-
Error Handling
- Upload invalid file type (e.g., .txt)
- Upload file > 5MB
- Try to enhance with empty content
- Try to save without authentication
- Verify error messages display
Test Upload:
curl -X POST http://localhost:5000/api/resume/upload \
-F "resume=@sample_resume.pdf" \
-vTest Register:
curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","password":"test123"}' \
-vTest Enhance:
curl -X POST http://localhost:5000/api/resume/enhance \
-H "Content-Type: application/json" \
-d '{"content":["Developed features"],"sectionType":"experience"}' \
-vTest with Auth:
TOKEN="your_jwt_token_here"
curl -X GET http://localhost:5000/api/resume/list \
-H "Authorization: Bearer $TOKEN" \
-v- Create new project on Railway or Render
- Connect GitHub repository
- Set environment variables:
MONGODB_URIGEMINI_API_KEYJWT_SECRETCLIENT_ORIGIN(frontend URL)
- Deploy from
serverdirectory
- Create new project on Vercel
- Set build settings:
- Framework: Vite
- Root Directory:
client - Build Command:
npm run build - Output Directory:
dist
- Add environment variable:
VITE_API_URL: Your backend URL
- Deploy
The generated PDFs follow these ATS-friendly guidelines:
β Single-column layout - No tables or multi-column formatting β Standard section headings - "Experience", "Education", "Skills" β Simple fonts - Arial/Helvetica for maximum compatibility β Text-based PDF - Not image/scanned document β Clear hierarchy - Consistent heading styles (H1, H2) β No graphics/images - Text only for ATS parsing β Standard date formats - "Month YYYY" format β Bullet points - Standard bullet lists, not custom symbols
- API keys stored in
.env(never commit) - Passwords hashed with bcrypt (10 rounds)
- JWT tokens expire after 7 days
- File upload size limited to 5MB
- CORS configured for specific origin
- Input validation on all endpoints
MongoDB Connection Failed:
Error: MongooseServerSelectionError
- Check
MONGODB_URIin.env - Verify MongoDB Atlas IP whitelist (allow 0.0.0.0/0 for development)
- Ensure database user has read/write permissions
Gemini API Error:
Failed to parse resume with AI
- Verify
GEMINI_API_KEYis valid - Check API quota limits
- Ensure resume text extracted successfully
File Upload Error:
Invalid file type
- Only PDF and DOCX files supported
- Max file size: 5MB
- Ensure file is not password-protected
TipTap Editor Not Loading:
- Check browser console for errors
- Ensure
@tiptap/reactand@tiptap/starter-kitinstalled - Clear node_modules and reinstall
ATS_RESUME_GENERATOR/
βββ server/
β βββ config/
β β βββ multer.config.js # File upload configuration
β βββ controllers/
β β βββ auth.controller.js # Authentication logic
β β βββ resume.controller.js # Resume CRUD operations
β βββ middleware/
β β βββ auth.middleware.js # JWT verification
β βββ models/
β β βββ User.model.js # User schema
β β βββ Resume.model.js # Resume schema
β βββ routes/
β β βββ auth.routes.js # Auth endpoints
β β βββ resume.routes.js # Resume endpoints
β βββ services/
β β βββ gemini.service.js # Gemini AI integration
β βββ utils/
β β βββ fileExtractor.js # PDF/DOCX extraction
β βββ uploads/ # Temporary file storage
β βββ .env.example # Environment template
β βββ package.json
β βββ server.js # Express app entry
β
βββ client/
β βββ src/
β β βββ components/
β β β βββ Layout.jsx # App layout wrapper
β β β βββ Navbar.jsx # Navigation bar
β β β βββ EditableSection.jsx # TipTap editor component
β β β βββ ResumePreview.jsx # PDF preview template
β β βββ context/
β β β βββ AuthContext.jsx # Auth state management
β β βββ pages/
β β β βββ Home.jsx # Landing page
β β β βββ Upload.jsx # File upload page
β β β βββ Editor.jsx # Resume editor
β β β βββ Dashboard.jsx # User resumes list
β β β βββ Login.jsx # Login form
β β β βββ Register.jsx # Registration form
β β βββ services/
β β β βββ api.js # Axios API client
β β βββ App.jsx # Router configuration
β β βββ main.jsx # React entry point
β β βββ index.css # Tailwind styles
β βββ index.html
β βββ package.json
β βββ vite.config.js
β βββ tailwind.config.js
β βββ postcss.config.js
β
βββ README.md
For detailed documentation, visit the docs/ directory:
- Quick Start Guides - Get started quickly with various features
- Implementation Reports - Detailed implementation documentation
- Testing Documentation - TestSprite and testing guides
- Monetization & Pricing - Business and pricing strategies
- Template Development - Create and customize resume templates
- Deployment Guide - Deploy to production
- Project Roadmap - Future features and plans
Contributions welcome! Please follow these steps:
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
MIT License - feel free to use this project for personal or commercial purposes.
- Google Gemini AI for intelligent parsing and enhancement
- TipTap for the excellent rich text editor
- React community for amazing tools and libraries
For issues, questions, or suggestions:
- Open a GitHub issue
- Check existing documentation
- Review troubleshooting section
Built with β€οΈ using MERN Stack + Gemini AI