DEV Community

MADHU SREE
MADHU SREE

Posted on

I Built an AI Resume Analyzer Using React, Express & Gemini API — Here's Everything I Learned"


After graduating, I found myself constantly refining my resume while waiting for onboarding updates. Every ATS checker gave generic advice, but none compared my resume against real job descriptions. I wanted a practical tool that could identify missing skills based on actual hiring requirements rather than assumptions.

That idea became Resume Brutalizer.

What Resume Brutalizer Does

Resume Brutalizer analyzes resumes against more than 215 real AI-related job descriptions collected from Indian companies. It:

✅ Extracts skills from your resume✅ Identifies skill gaps✅ Suggests improvements✅ Generates a personalized learning roadmap✅ Produces a resume score based on market demand

Live Demo

Try it now: https://resumebot-5dcrxpj7.manus.space/

GitHub: https://github.com/sreemadhu2609-pixel/resume-brutalizer-ai

Technology Stack

  • Frontend: React 19, TypeScript, Tailwind CSS

  • Backend: Express.js, Node.js, tRPC

  • Database: MySQL with Drizzle ORM

  • AI: Google Gemini API for resume analysis and structured skill extraction

  • Deployment: Google Cloud Run for scalable serverless hosting

Building the Project

Challenge 1: Data Collection

The first challenge was collecting quality job descriptions. I curated more than 215 listings from:

  • Company career pages

  • LinkedIn job boards

  • GitHub job listings

  • Hiring portals

Challenge 2: Resume Processing

I built a pipeline that:

  1. Parses PDF resumes

  2. Extracts text accurately

  3. Categorizes skills

  4. Compares against the dataset

  5. Generates personalized recommendations

Challenge 3: Prompt Engineering (The Biggest Challenge )

Early prompts produced inconsistent results. After multiple iterations, I designed structured prompts that grouped skills into categories:

  • Programming Languages

  • Frameworks

  • Databases

  • AI/ML Technologies

  • Cloud Platforms

  • Soft Skills

This significantly improved consistency and accuracy.

Key Learnings

1. Start with a Real Problem

Don't choose technologies first. Identify a real problem that you or others face, then choose the tech stack that solves it best.

Why it matters: You'll stay motivated because you're solving something meaningful.

2. Deploy Early

Production exposes issues that local testing never reveals. Deploy early, even if it's not perfect.

What I learned:

  • Database optimization issues only appeared under real load

  • UI/UX problems became obvious when real users tested it

  • Error handling gaps were discovered in production

3. Collect User Feedback Quickly

Small usability improvements often create the biggest impact.

Example: After the first user test, I realized the skill recommendations needed better formatting. One small change increased clarity by 50%.

4. Document Your Code

Document your code as you build to save debugging time later.

Pro tip: Future you will thank present you when you need to fix bugs or add features.

Technical Deep Dive

Frontend Architecture

// React component for resume upload
const ResumeUpload = () => {
  const { mutate: analyzeResume } = trpc.resume.analyze.useMutation();

  const handleUpload = async (file) => {
    const result = await analyzeResume({ file });
    // Display results
  };
};
Enter fullscreen mode Exit fullscreen mode

Backend Procedure

// tRPC procedure for resume analysis
export const resumeRouter = router({
  analyze: publicProcedure
    .input(z.object({ resumeText: z.string() }))
    .mutation(async ({ input }) => {
      // Extract skills
      const skills = await extractSkills(input.resumeText);

      // Compare with job descriptions
      const gaps = await findSkillGaps(skills);

      // Generate recommendations
      const recommendations = await generateRecommendations(gaps);

      return { skills, gaps, recommendations };
    })
});
Enter fullscreen mode Exit fullscreen mode

AI Integration

// Gemini API call for structured output
const response = await invokeLLM({
  messages: [
    { 
      role: "system", 
      content: "Extract skills from resume in JSON format" 
    },
    { 
      role: "user", 
      content: resumeText 
    }
  ],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "skills_extraction",
      schema: {
        type: "object",
        properties: {
          programming_languages: { type: "array" },
          frameworks: { type: "array" },
          databases: { type: "array" },
          ai_ml: { type: "array" },
          cloud: { type: "array" }
        }
      }
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Future Improvements

I plan to expand with:

🔜 500+ job descriptions (currently 215)🔜 AI-generated interview preparation🔜 Salary insights by skill🔜 Curated learning resources🔜 Community-driven success stories

Why This Matters

Building Resume Brutalizer strengthened my skills in:

✅ Full-stack development✅ Prompt engineering✅ Deployment and DevOps✅ Product thinking✅ Problem-solving

More importantly, it demonstrated how solving a real problem can become both a learning experience and a portfolio project that recruiters immediately understand.

Conclusion

If you're waiting for opportunities, don't wait passively. Build something. Solve a real problem. Document your journey.

Your next opportunity might be just one project away.


Connect With Me

Live Demo:https://resumebot-5dcrxpj7.manus.space/

GitHub: https://github.com/sreemadhu2609-pixel/resume-brutalizer-ai

Medium:https://medium.com/@madhusreesareddy

LinkedIn:https://linkedin.com/in/madhushree-sareddy

Have you built a project while waiting for opportunities? Share your story in the comments! 👇

Top comments (0)