How to Build a Chrome Extension with AI in One Afternoon

Build a working Chrome extension from scratch using Claude or Cursor. Manifest, scripts, publishing — everything you need in 4 hours.

By vibecodemeta 5 min read
chrome-extensions ai-coding productivity-tools tutorial

You can build a functional Chrome extension in one afternoon. Not a toy. Not a proof-of-concept. A real, publishable extension that does something useful.

This is what vibe coding was made for.

Why Chrome Extensions Are Perfect for Vibe Coding

Chrome extensions are small, scoped, and have clear success criteria. You’re not drowning in architectural decisions. You need a manifest file, a popup or background script, and maybe a content script. That’s it. The constraints actually help — your AI pair can’t overthink it.

Extensions also have immediate, visible results. You build it, reload the extension, click your icon, and boom — it works or it doesn’t. No deploy pipeline. No waiting. That feedback loop is addictive and that’s the point.

And the market for useful Chrome extensions is absurdly underfilled. People will pay for something that saves them 30 seconds a day.

The Anatomy of a Chrome Extension

Before we code, know what you’re building:

  • manifest.json — Tells Chrome what your extension is, what permissions it needs, what scripts to run
  • popup.html + popup.js — What appears when you click the extension icon (optional but common)
  • content.js — Runs on web pages you specify, can read/modify the page (optional)
  • background.js — Runs in the background, persists across tabs (optional for simple extensions)

Most useful extensions only need manifest.json, popup.html, and popup.js. Keep it simple.

Building Your Extension with Claude or Cursor

Here’s the workflow:

  1. Describe what you want clearly — “I want an extension that extracts all links from the current page and copies them to clipboard as markdown”
  2. Ask for the manifest.json first — Specific, unambiguous, less room for hallucination
  3. Then ask for the UI — popup.html and popup.js
  4. Test locally — Load unpacked into chrome://extensions
  5. Iterate — “Add a dark mode toggle” or “Make it copy as JSON instead”

The AI will get 80% right on the first try. You catch the bugs in real time because you’re testing as you go.

Let me walk through a real extension I built this way.

Step 1: The Manifest

{
  "manifest_version": 3,
  "name": "Link Extractor",
  "version": "1.0",
  "description": "Extract all links from the current page",
  "permissions": ["activeTab", "scripting"],
  "action": {
    "default_popup": "popup.html",
    "default_title": "Extract Links"
  },
  "icons": {
    "16": "images/icon16.png",
    "48": "images/icon48.png",
    "128": "images/icon128.png"
  }
}

Notice manifest_version: 3 (required for modern Chrome) and permissions: we only ask for what we need — activeTab to read the current tab, scripting to inject code.

Step 2: The Popup UI

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body {
      width: 400px;
      padding: 16px;
      font-family: system-ui, -apple-system, sans-serif;
      background: #f5f5f5;
    }
    .container {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }
    button {
      padding: 10px 16px;
      background: #4f46e5;
      color: white;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      font-size: 14px;
    }
    button:hover { background: #4338ca; }
    #output {
      background: white;
      border: 1px solid #e5e7eb;
      border-radius: 6px;
      padding: 12px;
      min-height: 100px;
      max-height: 300px;
      overflow-y: auto;
      font-size: 12px;
      font-family: monospace;
      white-space: pre-wrap;
    }
  </style>
</head>
<body>
  <div class="container">
    <h3 style="margin: 0;">Link Extractor</h3>
    <button id="extractBtn">Extract as Markdown</button>
    <button id="extractJson">Extract as JSON</button>
    <button id="copy">Copy to Clipboard</button>
    <div class="status" id="status"></div>
    <div id="output"></div>
  </div>
  <script src="popup.js"></script>
</body>
</html>

Simple, clean, actionable.

Step 3: The Popup Script

let currentLinks = [];

document.getElementById('extractBtn').addEventListener('click', () => {
  chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
    chrome.tabs.sendMessage(tabs[0].id, {action: 'getLinks'}, (response) => {
      if (response && response.links) {
        currentLinks = response.links;
        const markdown = response.links
          .map(link => `- [${link.text || 'no title'}](${link.url})`)
          .join('\n');
        document.getElementById('output').textContent = markdown;
      }
    });
  });
});

document.getElementById('copy').addEventListener('click', () => {
  const output = document.getElementById('output').textContent;
  navigator.clipboard.writeText(output).then(() => {
    document.getElementById('status').textContent = 'Copied!';
    setTimeout(() => { document.getElementById('status').textContent = ''; }, 2000);
  });
});

Step 4: The Content Script

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'getLinks') {
    const links = Array.from(document.querySelectorAll('a'))
      .map(a => ({ url: a.href, text: a.textContent.trim() }))
      .filter(link => link.url.startsWith('http'));
    sendResponse({links});
  }
});

That’s it. Four files. One afternoon.

Loading and Testing Locally

  1. Create a folder: link-extractor/
  2. Add manifest.json, popup.html, popup.js, and content.js
  3. Go to chrome://extensions/
  4. Enable “Developer mode” (top right)
  5. Click “Load unpacked”
  6. Select your folder
  7. Your extension appears in the toolbar

Now test it on any website. Click the icon. See the links. Change something in the code, reload the extension, test again. This cycle is fast. You’ll iterate 10 times in an hour.

Publishing to Chrome Web Store

Once it works:

  1. Create a 128x128 PNG icon
  2. Go to Chrome Web Store Developer Dashboard
  3. Pay the $5 registration fee (one time)
  4. Upload your extension folder as a .zip
  5. Fill in the store listing
  6. Submit for review (takes 1-3 hours usually)

Your extension will be live and searchable.

Where This Gets Real: Monetization

Most successful Chrome extensions follow this pattern: free tier with basic functionality, paid tier with unlimited features at $5-15/month, and a B2B tier for teams.

Even 100 paying users at $9/month is $900 MRR. That’s how you build revenue from small, useful tools.

Common Mistakes to Avoid

  • Over-engineering the manifest — You don’t need host_permissions for everything. Use specific permissions.
  • Publishing without testing — Test on 5 different websites before submitting. One-star reviews kill discovery.
  • Ignoring performance — If your content script runs on every tab, you’ll drain battery life. Be specific with matches.

Next Steps

Pick an annoyance you have. Something that takes you 30 seconds to do manually. That’s your extension idea.

Build it this afternoon using Claude or Cursor. Load it locally. Use it for a week. If you love it, publish it.

Want to get better at prompting your AI pair? Check out our prompt engineering guide. Need tools? See our directory for everything you need.

Join the Discussion