REST API for Real-e AI Classrooms, an interview-preparation product. It ingests job descriptions and candidate profiles (resume PDF/DOCX or free text), runs Google Gemini with schema-constrained JSON generation, persists structured reports in MongoDB, and can render tailored resume PDFs via headless Chrome.
Built for pairing with the companion frontend.
| Concern | Choice |
|---|---|
| Structured LLM output | Zod → JSON Schema → Gemini responseSchema (reduces hallucinated shapes and parsing pain) |
| Auth | JWT in httpOnly cookies + server-side token blacklist on logout |
| Files | Multer (memory) + pdf-parse for resume text extraction |
| PDF export | Puppeteer (HTML → PDF pipeline driven by a second Gemini call) |
| Data | Mongoose on MongoDB |
- Runtime: Node.js (CommonJS)
- Framework: Express 5.x
- Database: MongoDB via Mongoose 9.x
- AI:
@google/genai(Gemini), Zod + zod-to-json-schema - Auth:
jsonwebtoken,bcryptjs,cookie-parser - Uploads:
multer,pdf-parse - PDF:
puppeteer
server.js → bootstrap, PORT, dotenv
src/app.js → Express app, CORS, JSON, routes
src/config/ → database, cookie helpers
src/controllers/ → HTTP handlers
src/middlewares/ → JWT auth, file upload
src/models/ → User, InterviewReport, token blacklist
src/routes/ → auth + interview routers
src/services/ → Gemini orchestration (ai.service.js)
Authentication middleware verifies the JWT from cookies, checks the blacklist, and attaches req.user for protected routes.
Base path: /api
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/register |
Public | Register; sets auth cookie |
POST |
/login |
Public | Login; sets auth cookie |
GET |
/logout |
Public | Blacklists token, clears cookie |
GET |
/get-me |
JWT cookie | Current user profile |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/ |
JWT + multipart/form-data |
Job description, self-description, optional resume file → persisted AI report |
GET |
/ |
JWT | List current user’s reports (summary fields) |
GET |
/report/:interviewId |
JWT | Full report by ID (scoped to user) |
POST |
/resume/pdf/:interviewReportId |
JWT | Returns PDF blob tailored to stored context |
Interview generation merges resume text (from PDF when uploaded), self-description, and job description into the model prompt. Responses are validated against a Zod schema before persistence.
Copy .env.example to .env and fill in values. Never commit .env.
| Variable | Required | Purpose |
|---|---|---|
MONGODB_URI |
Yes | MongoDB connection string |
JWT_SECRET_KEY |
Yes | Secret for signing JWTs (use a long random string) |
GOOGLE_GENAI_API_KEY |
Yes | Gemini API key (server only) |
FRONTEND_ORIGIN |
Dev default | CORS allowed origin(s); comma-separated for multiple |
PORT |
No | Listen port (default 3000) |
AUTH_COOKIE_SAME_SITE |
No | e.g. none when SPA and API are on different sites (HTTPS required) |
AUTH_COOKIE_SECURE |
No | Force Secure cookies when needed |
Cookie options are centralized in src/config/cookies.js so Set-Cookie and clearCookie stay consistent.
cd Backend
cp .env.example .env # then edit .env
npm install
npm run devDefault URL: http://localhost:3000 (unless PORT is set).
Requirements:
- Running MongoDB instance (e.g. Atlas URI in
MONGODB_URI) - Valid
GOOGLE_GENAI_API_KEY - For PDF generation: Puppeteer will download/use Chromium; ensure the host allows headless browser execution (not ideal for naive serverless without extra configuration).
- Secrets live only in environment variables; the Gemini key must not appear in frontend bundles.
- CORS is explicit (
FRONTEND_ORIGIN); credentials are enabled for cookie-based auth. - JWTs are stored in httpOnly cookies to mitigate XSS token theft; tune
sameSite/securefor your deployment topology. - Logout blacklists the current token so it cannot be reused after sign-out.
- Set all required env vars on the host.
- Point
FRONTEND_ORIGINat your deployed SPA URL(s). - Use HTTPS; configure cookie flags for cross-site setups if needed.
- Confirm MongoDB network access and IP allowlists (Atlas).
- Validate Puppeteer/Chromium works on your platform or move PDF generation to a worker/container.
Licensed under "𝔩𝔢𝔞𝔯𝔫𝔦𝔫𝔤 𝔣𝔬𝔯 𝔱𝔥𝔢 𝔧𝔬𝔲𝔯𝔫𝔢𝔶, 𝔫𝔬𝔱 𝔱𝔥𝔢 𝔡𝔢𝔰𝔱𝔦𝔫𝔞𝔱𝔦𝔬𝔫".