I Built an AI Resume Analyzer Using Gemini API + FastAPI + React 🚀

Built for HackFest 2026 | Theme: AI & Smart Automation


The Problem

Most resume analyzers are generic. They slap a score on your resume, tell you to "add more keywords," and call it a day.

But here's the real problem — especially for students and early-career developers: we don't know why our bullet points are weak, or how to fix them in a way that actually impresses a recruiter.

So for HackFest 2026, I built ResumeIQ — an AI-powered resume analyzer that doesn't just score your resume, it teaches you how to rewrite it using the same framework Google's hiring team uses: the XYZ format.

"Accomplished X, measured by Y, by doing Z."


What It Does

Upload your PDF resume and ResumeIQ gives you:

  • 📊 Overall ATS Score (0–100) — how likely your resume passes an Applicant Tracking System
  • 🧠 Candidate Summary — a 2-3 sentence profile of who you are on paper
  • Top Strengths — what you're already doing right
  • ⚠️ Critical Missing Skills — what's holding you back
  • 📝 Formatting Feedback — layout, readability, and typo checks
  • 🔁 Bullet Point Rewrites — takes your weak bullets and rewrites them in XYZ format, with reasoning explaining why the new version is stronger

Tech Stack

Layer Technology
Frontend React (single HTML file, no build step)
Backend Python + FastAPI
AI Google Gemini 1.5 Flash (gemini-1.5-flash)
PDF Parsing pdfplumber
Env Management python-dotenv

Architecture

User uploads PDF
      ↓
React Frontend (index.html)
      ↓  POST /analyze (multipart/form-data)
FastAPI Backend (main.py)
      ↓  pdfplumber extracts text
      ↓  Prompt sent to Gemini API
      ↓  Gemini returns structured JSON
      ↑  Response rendered in UI

The API key lives only on the backend in a .env file — users never see or touch it.


The Gemini Prompt (The Real Magic)

The entire intelligence of this app lives in one carefully engineered prompt. I instructed Gemini to act as an elite ATS and technical recruiter, and to return a strictly typed JSON object — no markdown, no prose, just clean structured data.

generation_config=genai.types.GenerationConfig(
    response_mime_type="application/json",
)

Using response_mime_type="application/json" forces Gemini to return valid JSON every time — no need to strip markdown fences or handle parsing errors from free-form text.

The prompt extracts actual bullet points from the resume and rewrites them using the XYZ format:

Before: "Worked on backend APIs"

After: "Engineered 15+ RESTful APIs using FastAPI, reducing average response latency by 30% across 3 production services"

Reasoning: "The original gives no context on scale, technology, or impact. The rewrite quantifies scope and outcome, which is what ATS systems and recruiters scan for."


What Makes This Different

Most resume tools are built for experienced professionals. ResumeIQ is built for students and early-career developers — people who have the skills but don't know how to communicate them.

The XYZ rewrite feature is the core differentiator. Instead of just flagging weak bullets, it models the thinking behind strong writing. Over time, users don't just fix their resume — they learn to write better bullets from scratch.


Running It Locally

Backend:

cd resume-analyzer-backend
pip install -r requirements.txt

# Add your Gemini API key to .env
echo "GEMINI_API_KEY=your_key_here" > .env

uvicorn main:app --reload
# Runs on http://localhost:8000

Frontend:

cd resume-analyzer-frontend
# Just open index.html in your browser — no npm, no build step needed!

Challenges I Faced

1. Getting structured JSON from an LLM reliably Early versions used free-form prompts and I had to strip markdown fences and handle malformed JSON. Switching to response_mime_type="application/json" in the Gemini API config completely solved this.

2. PDF text extraction quality pdfplumber works great for text-based PDFs but fails on scanned/image PDFs. I added a minimum text length check and a clear error message so users know what went wrong instead of getting a silent failure.

3. Prompt engineering for consistent output Getting Gemini to always extract actual bullet points from the resume (not made-up ones) required being very explicit in the prompt with examples of good vs. bad rewrites.


What's Next

  • [ ] Job description input for targeted ATS keyword matching
  • [ ] Role selector (SWE / Data Science / Product) for domain-specific feedback
  • [ ] Side-by-side resume diff view
  • [ ] Export improved resume as PDF

Built With


Built solo in 24 hours for HackFest 2026 — AI & Smart Automation track.

If you found this useful or have feedback, drop a comment below! 👇

Tags: #hackathon #ai #python #react #gemini #webdev #beginners

Built With

Share this project:

Updates