Back to Case Studies

Chrome Extension for AI-Powered Resume Tailoring

Manifest V3 Chrome extension with React, TypeScript, and Claude API for intelligent job application assistance

Chrome ExtensionManifest V3ReactTypeScriptClaude APITailwindCSS

Overview

Developed a Chrome extension that detects job postings on LinkedIn, Indeed, and other job sites, then uses Claude API to intelligently reframe resume experience using the job posting's language. Never fabricates experience - only translates existing skills into target vocabulary.

The Problem

Job seekers submit the same generic resume to every application. ATS systems scan for keyword matches. The disconnect: you have the skills but describe them differently than the job posting. Manual tailoring takes 20-30 minutes per application.

Architecture Decisions

Why Manifest V3?

Required for Chrome Web Store as of 2024. Service workers for background processing. Better security model.

Why React in an extension?

Popup and options pages benefit from component architecture. State management for complex UI. Reuse of existing React knowledge.

Why user-provided API key?

No backend server needed. User controls their own usage/costs. Privacy: resume data never touches a third-party server.

Key Features

  • Job Detection: Auto-detects job postings on LinkedIn, Indeed, Hiring Cafe
  • Resume Reframing: Translates experience into job posting vocabulary
  • Match Score: Calculates fit percentage based on skill overlap
  • Cover Letter Generation: Creates tailored cover letters
  • Application Tracker: Track status across applications

Challenges & Solutions

ChallengeSolution
Manifest V3 service worker limitsImplemented message passing for long operations
Job site DOM variationsBuilt fallback selectors and regex patterns
API key securityStored in chrome.storage.local (never synced)
Large resume + job posting contextChunked processing with context summaries

Results

  • Reduces tailoring time from 25 min to 2 min per application
  • 85%+ match scores on targeted applications
  • Zero fabrication - verified through diff comparison
  • Tracks 50+ applications with status management

Code Sample - Resume Reframing

typescript
// Service Worker - Claude Integration
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'REFRAME_RESUME') {
    reframeResume(request.resume, request.jobPosting)
      .then(result => sendResponse({ success: true, result }))
      .catch(error => sendResponse({ success: false, error: error.message }));
    return true; // Keep channel open for async response
  }
});

async function reframeResume(resume: string, jobPosting: JobPosting) {
  const apiKey = await chrome.storage.local.get('claudeApiKey');

  const response = await fetch('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey.claudeApiKey,
      'anthropic-version': '2023-06-01'
    },
    body: JSON.stringify({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 4096,
      messages: [{
        role: 'user',
        content: buildReframePrompt(resume, jobPosting)
      }]
    })
  });

  const data = await response.json();
  return parseReframedResume(data.content[0].text);
}

What I'd Do Differently

  • Add support for more job sites (Glassdoor, ZipRecruiter)
  • Build comparison view (original vs reframed)
  • Implement batch processing for multiple job applications