I Built an AI Resume Analyzer With Gemini — Here’s What Actually Worked 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. After graduating, I found myself doing something I suspect many developers experience constantly rewriting my resume while trying to understand what companies actually wanted. I tried different ATS checkers, but most of them gave me generic suggestions. Add more keywords. Improve your formatting. Make your resume more concise. But I wanted something different. I wanted to know: How does my resume compare with the skills companies are actually asking for? That question became the starting point for Resume Brutalizer , an AI-powered resume analyzer I built around real job-market data. The basic idea was simple: Upload a resume → analyze its skills → compare them against real job requirements → identify gaps → generate personalized recommendations. Instead of relying entirely on a generic ATS score, I wanted the application to understand what employers were actually looking for. I eventually collected more than 215 AI-related job descriptions from companies hiring in India . That dataset became one of the most important parts of the project. The application could then look at a resume and answer questions such as: That turned the project from a simple AI wrapper into something closer to a job-market-aware resume analysis tool . I built the application using: The important part wasn’t choosing the most fashionable technology. It was figuring out where each piece actually belonged. The high-level flow looked roughly like this: ┌─────────────────┐ │ Resume Upload │ └────────┬────────┘ ↓ ┌─────────────────┐ │ Resume Parsing │ └────────┬────────┘ ↓ ┌─────────────────┐ │ Skill Extraction│ └────────┬────────┘ ↓ ┌───────────────┴───────────────┐ ↓ ↓ Job Description Dataset Gemini Analysis │ │ └───────────────┬───────────────┘ ↓ ┌─────────────────┐ │ Recommendations │ └─────────────────┘ The architecture evolved significantly as I built the application. And that’s where things became interesting. The React interface wasn’t the biggest challenge. The difficult part was getting the analysis itself to be consistent . My first prompts were too open-ended. I could provide the same resume and job description and sometimes receive noticeably different structures or levels of detail. That wasn’t good enough. A resume analyzer needs predictable output. If one analysis returns: PythonReactSQLAWS while another returns: Python: StrongFrontend: ModerateDatabase: GoodCloud: Limited it becomes difficult to build reliable UI components around those responses. So I changed the way I approached prompting. Instead of asking Gemini to simply “analyze this resume,” I started defining the output more carefully. I grouped skills into categories such as: The model was then given a much clearer structure to work with. This made the output easier to process and display. More importantly, it taught me an important lesson: When you’re building an application around an LLM, the prompt is part of your application’s interface. You can’t treat it like a magic text box. You have to think about inputs, outputs, consistency, validation, and failure cases. Collecting the job descriptions was one of the most time-consuming parts of the project. I didn’t want to build recommendations around assumptions about what employers wanted. I wanted actual job requirements. So I curated more than 215 AI-related job descriptions from Indian companies and used them as the foundation for identifying recurring skills and requirements. That gave the application something a generic AI resume analyzer doesn’t necessarily have: context. For example, instead of simply asking: “What skills should this candidate learn?” the system could reason around: “What skills are appearing repeatedly in the type of roles this candidate is targeting?” That distinction matters. AI can generate recommendations. But better data gives those recommendations better context. The backend started relatively simply. As features increased, I needed clear separation between: That’s where tRPC became useful. Instead of manually maintaining separate API contracts between the frontend and backend, I could define procedures with shared TypeScript types. For example: resume.getHistoryresume.analyzeresume.upload The frontend could then consume those procedures with type information carried across the application. That reduced repetitive code and made development easier. The first version of the application treated the database too much like a storage bucket. As the application grew, I realized that resume information, users, and analysis results needed clearer relationships. The structure evolved toward separate entities such as: Users │ └── Resumes │ └── Resume Analyses I also added indexes for frequently queried relationships. This was a good reminder that: A prototype can survive messy data structures. A growing application usually can’t. Building Resume Brutalizer changed how I think about AI-powered applications. Adding Gemini doesn’t automatically create a useful AI application. The surrounding system matters: Data → preprocessing → prompt → model → validation → application logic → user experience The model is one component in that pipeline. The 215+ job descriptions gave the application context that a generic prompt wouldn’t have. The 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. I initially thought prompt engineering would be a small part of the project. It wasn’t. I had to think about: That’s surprisingly similar to designing any other software interface. Everything can look perfect on localhost. Then you deploy. Suddenly you discover problems involving: Deploying early taught me more than waiting until the application was “finished.” If I started Resume Brutalizer again, I would spend more time on the architecture and data model before writing the first components. I would also establish a structured AI output format earlier. And I would build evaluation cases for the AI analysis instead of manually checking whether individual responses “looked good.” That would have made the development process much more predictable. Resume Brutalizer is still a learning project for me. The next improvements I’d like to explore include: The goal isn’t simply to produce another resume score. I want the application to help answer a more useful question: “Given where I am today and the roles I’m targeting, what should I do next?” The biggest thing I learned wasn’t React. It wasn’t Express. It wasn’t Gemini. It was that building an AI product is much more than calling an API. You need the data. You need the architecture. You need predictable inputs and outputs. You need validation. You need a useful user experience. And most importantly, you need a real problem worth solving. Resume Brutalizer started as an idea I had while trying to improve my own resume. Building 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. The interesting part wasn’t that I used Gemini. It was everything I had to build around it to make Gemini useful. GitHub: github.com/sreemadhu2609-pixel LinkedIn: linkedin.com/in/madhushree-sareddy Project: resumebot-5dcrxpj7.manus.space 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.