PrepAI is a full-stack web application that analyzes your resume against a job description using Google Gemini AI, generates a detailed interview report, and produces a tailored, ATS-friendly resume PDF β all in one place.
- Upload your resume (PDF) or write a self-description
- Paste any job description
- Gemini AI analyzes the match and generates:
- Match Score (0β100) β how well your profile fits the role
- Technical Questions β with interviewer intention + how to answer
- Behavioral Questions β with context and suggested answers
- Skill Gaps β missing skills with severity (low / medium / high)
- Day-wise Preparation Roadmap β structured plan to prepare
- Generates a tailored, ATS-friendly resume based on your profile and the target job description
- Resume is formatted in clean HTML by Gemini AI
- Converted to a downloadable A4 PDF using Puppeteer
- One-click download from the interview report page
- JWT-based authentication using access + refresh tokens
- Tokens stored in HTTP-only cookies (XSS safe)
- OTP email verification on signup
- Token blacklisting on logout (stored in DB)
- Protected routes on both frontend and backend
- View all previously generated interview reports
- Each report stores: match score, job title, resume, self-description
- Click any report to revisit the full interview analysis
| Technology | Usage |
|---|---|
| Node.js + Express.js | REST API server |
| TypeScript | Type safety |
| Prisma ORM | Database queries |
| PostgreSQL | Relational database |
Google Gemini AI (gemini-2.5-flash) |
AI report + resume generation |
| Puppeteer | HTML to PDF conversion |
| Zod | Input validation + AI schema enforcement |
zod-to-json-schema |
Convert Zod schema to JSON Schema for Gemini |
pdf-parse |
Extract text from uploaded resume PDF |
| Multer | File upload handling |
| JWT | Authentication tokens |
| Nodemailer | OTP email sending |
| bcrypt | Password hashing |
| Technology | Usage |
|---|---|
| React + TypeScript | UI framework |
| Vite | Build tool |
| React Router v6 | Client-side routing |
| Axios | HTTP requests |
| Tailwind CSS | Styling |
| Lucide React | Icons |
| Context API | Global state management |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend β
β React + TypeScript + Context API + Axios β
β β
β Pages: Home β InterviewPage β Dashboard β
β Hooks: useInterview, useAuth β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β HTTP (withCredentials: true)
β Cookies (JWT tokens)
ββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β Backend β
β Express.js + TypeScript β
β β
β Routes: β
β POST /api/auth/signup β
β POST /api/auth/login β
β GET /api/auth/logout β
β GET /api/auth/get-me β
β POST /api/interview (generate report) β
β GET /api/interview (all reports) β
β GET /api/interview/report/:id β
β POST /api/interview/resume/pdf/:id β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
βββββββββββββ΄ββββββββββββ
β β
ββββββββββΌβββββββββ βββββββββββΌβββββββββ
β PostgreSQL β β Google Gemini β
β via Prisma β β AI API β
β β β β
β Users β β generateContent β
β InterviewReportβ β JSON Schema β
β TechnicalQ β β enforced via β
β BehavioralQ β β Zod β
β SkillGap β ββββββββββββββββββββ
β PreparationPlanβ
β Otp β
β Blacklist β
βββββββββββββββββββ
User
βββ id, username, email, password, verified
βββ reports[] βββ InterviewReport
βββ matchScore, title, jobDescription
βββ technicalQuestion[]
βββ behavioralQuestions[]
βββ skillGaps[]
βββ preparationPlan[]Relations are one-to-many β one user has many reports, one report has many questions.
1. Resume PDF uploaded β text extracted via pdf-parse
2. Text + selfDescription + jobDescription sent to Gemini
3. Zod schema defines exact output structure
4. zod-to-json-schema converts it to JSON Schema
5. Gemini returns structured JSON (enforced by schema)
6. Data saved to PostgreSQL via Prisma nested writes
1. Resume text + job description sent to Gemini
2. Gemini generates tailored HTML resume (inline CSS, A4 size)
3. Puppeteer opens HTML in headless Chrome
4. page.pdf() converts it to PDF buffer
5. Buffer sent to frontend as application/pdf blob
6. Frontend creates download link and triggers download
Gemini supports structured output via JSON Schema. Instead of writing raw JSON Schema manually, Zod schemas are written in TypeScript and converted automatically β giving both type safety and AI output enforcement.
β οΈ Note:zod-to-json-schemaconverts camelCase keys to snake_case. SomatchScorein Zod becomesmatch_scorein Gemini's response. Handle this in your backend mapping.
GenAi-PrepAI/
βββ backend/
β βββ src/
β β βββ config/ # DB connection (Prisma)
β β βββ controller/ # Route handlers
β β βββ middleware/ # Auth middleware
β β βββ routes/ # Express routers
β β βββ services/ # AI logic (Gemini + Puppeteer)
β β βββ utils/ # Zod schemas, helpers
β β βββ generated/ # Prisma generated client
β βββ prisma/
β β βββ schema.prisma
β βββ package.json
β
βββ frontend/
βββ src/
β βββ features/
β β βββ interview/
β β βββ components/ # Interview UI components
β β βββ hooks/ # useInterview
β β βββ services/ # API calls
β β βββ types/ # TypeScript types
β βββ pages/ # Home, Dashboard, InterviewPage
β βββ App.tsx
βββ package.json
- Node.js 18+
- PostgreSQL database
- Google Gemini API key
- pnpm (or npm)
git clone https://github.com/amankarn2007/GenAi-PrepAI.git
cd GenAi-PrepAIcd backend
pnpm installCreate .env:
DATABASE_URL=postgresql://user:password@localhost:5432/prepai
GEMINI_API_KEY=your_gemini_api_key
JWT_ACCESS_SECRET=your_access_secret
JWT_REFRESH_SECRET=your_refresh_secret
EMAIL_USER=your_email@gmail.com
EMAIL_PASS=your_app_password
NODE_ENV=developmentnpx prisma migrate dev
npx prisma generate
npx puppeteer browsers install chrome
pnpm devcd frontend
pnpm installCreate .env:
VITE_API_URL=http://localhost:3000pnpm devRoot Directory: backend
Build Command: pnpm install && npx prisma generate && npx prisma migrate deploy && npx puppeteer browsers install chrome && pnpm build
Start Command: pnpm start
Environment variables: same as .env above (add production values)
Root Directory: frontend
Build Command: pnpm install && pnpm build
Publish Directory: dist
Environment variables:
VITE_API_URL = https://your-backend.onrender.com
Home Page β Interview Report β Dashboard β PDF Download
MIT License β feel free to use and modify.
Aman Kumar Karn
- GitHub: @amankarn2007
- LinkedIn: linkedin.com/in/karnaman