{"slug": "i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked", "title": "I Built an AI Resume Analyzer With Gemini — Here’s What Actually Worked", "summary": "A developer built Resume Brutalizer, an AI-powered resume analyzer using Google's Gemini, which compares resumes against a dataset of more than 215 AI-related job descriptions from Indian companies to identify skill gaps and generate personalized recommendations. The project highlighted the importance of structuring prompts for consistent LLM output, treating the prompt as part of the application's interface.", "body_md": "After graduating, I found myself doing something I suspect many developers experience **constantly rewriting my resume while trying to understand what companies actually wanted.**\n\nI tried different ATS checkers, but most of them gave me generic suggestions.\n\nAdd more keywords.\n\nImprove your formatting.\n\nMake your resume more concise.\n\nBut I wanted something different.\n\nI wanted to know:\n\nHow does my resume compare with the skills companies are actually asking for?\n\nThat question became the starting point for **Resume Brutalizer**, an AI-powered resume analyzer I built around real job-market data.\n\nThe basic idea was simple:\n\n**Upload a resume → analyze its skills → compare them against real job requirements → identify gaps → generate personalized recommendations.**\n\nInstead of relying entirely on a generic ATS score, I wanted the application to understand what employers were actually looking for.\n\nI eventually collected **more than 215 AI-related job descriptions from companies hiring in India**.\n\nThat dataset became one of the most important parts of the project.\n\nThe application could then look at a resume and answer questions such as:\n\nThat turned the project from a simple AI wrapper into something closer to a **job-market-aware resume analysis tool**.\n\nI built the application using:\n\nThe important part wasn’t choosing the most fashionable technology.\n\nIt was figuring out where each piece actually belonged.\n\nThe high-level flow looked roughly like this:\n\n```\n┌─────────────────┐                    │   Resume Upload │                    └────────┬────────┘                             ↓                    ┌─────────────────┐                    │  Resume Parsing │                    └────────┬────────┘                             ↓                    ┌─────────────────┐                    │ Skill Extraction│                    └────────┬────────┘                             ↓             ┌───────────────┴───────────────┐             ↓                               ↓     Job Description Dataset          Gemini Analysis             │                               │             └───────────────┬───────────────┘                             ↓                    ┌─────────────────┐                    │ Recommendations │                    └─────────────────┘\n```\n\nThe architecture evolved significantly as I built the application.\n\nAnd that’s where things became interesting.\n\nThe React interface wasn’t the biggest challenge.\n\nThe difficult part was getting the **analysis itself to be consistent**.\n\nMy first prompts were too open-ended.\n\nI could provide the same resume and job description and sometimes receive noticeably different structures or levels of detail.\n\nThat wasn’t good enough.\n\nA resume analyzer needs predictable output.\n\nIf one analysis returns:\n\n```\nPythonReactSQLAWS\n```\n\nwhile another returns:\n\n```\nPython: StrongFrontend: ModerateDatabase: GoodCloud: Limited\n```\n\nit becomes difficult to build reliable UI components around those responses.\n\nSo I changed the way I approached prompting.\n\nInstead of asking Gemini to simply “analyze this resume,” I started defining the output more carefully.\n\nI grouped skills into categories such as:\n\nThe model was then given a much clearer structure to work with.\n\nThis made the output easier to process and display.\n\nMore importantly, it taught me an important lesson:\n\nWhen you’re building an application around an LLM, the prompt is part of your application’s interface.\n\nYou can’t treat it like a magic text box.\n\nYou have to think about inputs, outputs, consistency, validation, and failure cases.\n\nCollecting the job descriptions was one of the most time-consuming parts of the project.\n\nI didn’t want to build recommendations around assumptions about what employers wanted.\n\nI wanted actual job requirements.\n\nSo I curated more than **215 AI-related job descriptions from Indian companies** and used them as the foundation for identifying recurring skills and requirements.\n\nThat gave the application something a generic AI resume analyzer doesn’t necessarily have:\n\n**context.**\n\nFor example, instead of simply asking:\n\n“What skills should this candidate learn?”\n\nthe system could reason around:\n\n“What skills are appearing repeatedly in the type of roles this candidate is targeting?”\n\nThat distinction matters.\n\nAI can generate recommendations.\n\nBut **better data gives those recommendations better context.**\n\nThe backend started relatively simply.\n\nAs features increased, I needed clear separation between:\n\nThat’s where **tRPC** became useful.\n\nInstead of manually maintaining separate API contracts between the frontend and backend, I could define procedures with shared TypeScript types.\n\nFor example:\n\n```\nresume.getHistoryresume.analyzeresume.upload\n```\n\nThe frontend could then consume those procedures with type information carried across the application.\n\nThat reduced repetitive code and made development easier.\n\nThe first version of the application treated the database too much like a storage bucket.\n\nAs the application grew, I realized that resume information, users, and analysis results needed clearer relationships.\n\nThe structure evolved toward separate entities such as:\n\n```\nUsers   │   └── Resumes          │          └── Resume Analyses\n```\n\nI also added indexes for frequently queried relationships.\n\nThis was a good reminder that:\n\nA prototype can survive messy data structures. A growing application usually can’t.\n\nBuilding Resume Brutalizer changed how I think about AI-powered applications.\n\nAdding Gemini doesn’t automatically create a useful AI application.\n\nThe surrounding system matters:\n\n**Data → preprocessing → prompt → model → validation → application logic → user experience**\n\nThe model is one component in that pipeline.\n\nThe 215+ job descriptions gave the application context that a generic prompt wouldn’t have.\n\nThe more I worked on the project, the more I realized that the quality of the surrounding data and logic determines how useful the final experience feels.\n\nI initially thought prompt engineering would be a small part of the project.\n\nIt wasn’t.\n\nI had to think about:\n\nThat’s surprisingly similar to designing any other software interface.\n\nEverything can look perfect on localhost.\n\nThen you deploy.\n\nSuddenly you discover problems involving:\n\nDeploying early taught me more than waiting until the application was “finished.”\n\nIf I started Resume Brutalizer again, I would spend more time on the architecture and data model before writing the first components.\n\nI would also establish a structured AI output format earlier.\n\nAnd I would build evaluation cases for the AI analysis instead of manually checking whether individual responses “looked good.”\n\nThat would have made the development process much more predictable.\n\nResume Brutalizer is still a learning project for me.\n\nThe next improvements I’d like to explore include:\n\nThe goal isn’t simply to produce another resume score.\n\nI want the application to help answer a more useful question:\n\n“Given where I am today and the roles I’m targeting, what should I do next?”\n\nThe biggest thing I learned wasn’t React.\n\nIt wasn’t Express.\n\nIt wasn’t Gemini.\n\nIt was that **building an AI product is much more than calling an API.**\n\nYou need the data.\n\nYou need the architecture.\n\nYou need predictable inputs and outputs.\n\nYou need validation.\n\nYou need a useful user experience.\n\nAnd most importantly, you need a real problem worth solving.\n\nResume Brutalizer started as an idea I had while trying to improve my own resume.\n\nBuilding it turned that frustration into a real engineering project — and gave me a much better understanding of what it actually takes to build software around AI.\n\n**The interesting part wasn’t that I used Gemini.**\n\nIt was everything I had to build around it to make Gemini useful.\n\n**GitHub:** github.com/sreemadhu2609-pixel\n\n**LinkedIn:** linkedin.com/in/madhushree-sareddy\n\n**Project:** resumebot-5dcrxpj7.manus.space\n\n[I Built an AI Resume Analyzer With Gemini — Here’s What Actually Worked](https://blog.stackademic.com/i-built-an-ai-resume-analyzer-using-react-express-gemini-api-heres-everything-i-learned-5d876def08b2) was originally published in [Stackademic](https://blog.stackademic.com) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked", "canonical_source": "https://blog.stackademic.com/i-built-an-ai-resume-analyzer-using-react-express-gemini-api-heres-everything-i-learned-5d876def08b2?source=rss----d1baaa8417a4---4", "published_at": "2026-08-21 06:39:09+00:00", "updated_at": "2026-08-21 07:13:07.230764+00:00", "lang": "en", "topics": ["artificial-intelligence", "generative-ai", "ai-products", "developer-tools"], "entities": ["Gemini", "Resume Brutalizer"], "alternates": {"html": "https://wpnews.pro/news/i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked", "markdown": "https://wpnews.pro/news/i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked.md", "text": "https://wpnews.pro/news/i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked.txt", "jsonld": "https://wpnews.pro/news/i-built-an-ai-resume-analyzer-with-gemini-heres-what-actually-worked.jsonld"}}