Project Overview
HireGenie is an AI-powered career assistant that gets candidates interview-ready instead of just scoring them. Upload a resume and paste a job description, and HireGenie returns a match score, real interview questions with the reasoning behind each one and how to answer it, ranked skill gaps, a day-wise study plan, and a rewritten ATS-friendly resume rendered as a PDF. Built on React, Express 5, MongoDB, Gemini, and Puppeteer, the platform deliberately separates heavy AI work into a queue-driven worker so the API stays responsive under real traffic.
Solution
HireGenie's core structural decision is separating 'accepting the request' from 'doing the expensive work'. When a user submits a report request, the controller validates auth and the file upload, extracts text from the resume PDF with pdf-parse, and immediately enqueues a job on a BullMQ-backed queue, returning HTTP 202 with a jobId. A separate worker process (same codebase, separate entrypoint) consumes the queue, runs the Gemini generation with a Zod-derived JSON schema, persists the report to MongoDB, and emits a report:complete event to the user's socket.io room. Clients can also poll the job-status endpoint. The same pattern powers resume PDF generation: Gemini produces structured HTML, Puppeteer renders it to an A4 PDF, and the result is delivered asynchronously.
Architecture

Core Features
Match Score
Gemini produces a 0-100 alignment score between the candidate profile and the job description. The score is derived from structured analysis rather than keyword matching, so it reflects genuine fit rather than buzzword overlap.
Interview Questions with Intention & Answers
The report separates technical from behavioral questions. Each question includes the interviewer's intention behind asking it and a structured answer covering the points, approach, and structure a candidate should deliver.
Ranked Skill Gap Detection
Missing skills are listed with a low/medium/high severity rating reflecting how much the gap impacts the candidate's chances for the specific role, not a generic suggestion list.
Day-Wise Preparation Plan
A numbered, day-by-day plan with a focus area and concrete tasks per day (reading, problem sets, mock interviews). A real schedule instead of 'study more'.
Tailored ATS-Friendly Resume PDF
Gemini generates structured HTML for a resume rebuilt around the target job, styled to be simple and professional, explicitly optimized for ATS parsability. Puppeteer renders it to an A4 PDF asynchronously.
Async Job Pipeline & Live Progress
Every generation runs through BullMQ with a dedicated worker, returning 202 immediately and streaming completion via socket.io. The request path never blocks on the model.
Engineering Challenges
The Gemini call blocked the request
The original flow held the HTTP connection open for the full 15-20 seconds of model generation. The fix was structural: enqueue and return 202, then run generation in a worker. Clients either listen on socket.io or poll the job status.
Puppeteer in the request path
Launching headless Chrome per PDF is memory- and CPU-expensive. Moving it to the worker process (with --no-sandbox flags for Docker) meant a slow PDF generation could no longer hold up other requests.
No backpressure on AI calls
Ten concurrent users used to mean ten concurrent Gemini calls. BullMQ's Redis-backed queue introduces natural throttling, persistence across restarts, and automatic retry for failed jobs.
Thin, growing authentication
Single JWT with no rotation, no cookie flags, and a blacklist collection that grew forever. Hardened with httpOnly cookies, CORS credentials, and a TTL-indexed blacklist so expired tokens clean themselves up.
No validation layer
Controllers assumed well-formed bodies. Zod schemas per route now reject malformed requests before they reach controllers or the AI provider.
Technical Decisions
Gemini + Zod schema, not free-form prompts
The report is too structured to trust free-form model output. Every generation uses a Zod schema converted to a JSON schema via zod-to-json-schema, guaranteeing the model returns the exact shape the app persists.
BullMQ + Redis over in-process queues
Background promises die with the server and vanish on deploy. A Redis-backed queue persists jobs, retries failures, and lets the worker scale independently, the foundation every other decision builds on.
Separate worker process over setImmediate
In-flight work must survive restarts and autoscaling events. A real queue with a separate worker entrypoint makes Gemini the only bottleneck, and adding workers is a deployment change, not a code change.
Cookie-based JWT with blacklist revocation
Token-in-localStorage invites XSS theft, so auth rides on a cookie with the frontend sending credentials: 'include', and a blacklist collection supports explicit logout and revocation. Hardening to secure/sameSite flags and refresh-token rotation is on the documented roadmap.
Puppeteer for PDF generation
Gemini already outputs HTML; rendering that HTML to an exact A4 PDF with margins and network-idle waiting gives deterministic, pixel-faithful resumes without a separate templating engine.
MongoDB with Mongoose
Interview reports are deeply nested, heterogeneous documents (questions, gaps, plans). A document store maps to the report shape directly and avoids the join-heavy schema a relational model would demand.
Performance Considerations
- AI and PDF work never block the API. The queue + worker architecture keeps p95 response time flat regardless of Gemini latency.
- List endpoints project away heavy fields (resume text, questions, plans) so report history stays fast as it grows.
- Worker parallelism can scale independently of API instances; Gemini throughput is the only real bottleneck.
- Puppeteer runs once per PDF job in the worker, isolating its memory footprint from the web tier.