DEV Community

miccho27
miccho27

Posted on

Chrome Extension Development Tips — What I Learned Publishing 11 Extensions

Chrome Extension Development Tips — What I Learned Publishing 11 Extensions

I built and submitted 11 Chrome extensions to the Chrome Web Store. Two are live, one is in review, and eight are pending. Here's everything I wish I'd known before starting.


The 11 Extensions

Extension Category Status
Tab Manager Pro Productivity Published
Quick Notes Productivity Published
Hash & Encode Tool Developer Tools In Review
Color Picker Pro Developer Tools Pending
JSON Formatter Developer Tools Pending
Readability Score Writing Pending
SEO Meta Checker SEO Pending
Bookmark Organizer Productivity Pending
Page Speed Checker Developer Tools Pending
Dark Mode Toggle Accessibility Pending
Screenshot Capture Utility Pending

Tip 1: Use Manifest V3 from Day One

Manifest V2 is deprecated. Google won't accept new V2 extensions. Don't waste time learning V2 patterns.

Key V3 changes:

  • background.js → Service Workers (no persistent background page)
  • chrome.browserActionchrome.action
  • Remote code execution is blocked (no eval(), no remote scripts)
  • content_security_policy is stricter
{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icons/icon-48.png"
  },
  "permissions": ["storage", "activeTab"],
  "background": {
    "service_worker": "background.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Tip 2: Request Minimum Permissions

Chrome Web Store reviewers scrutinize permissions. Request only what you need:

Permission Use When
activeTab Need access to current tab only (preferred over tabs)
storage Saving user preferences
tabs Need to list/manage all tabs
clipboardWrite Copy-to-clipboard feature
host_permissions API calls to specific domains

Never request: <all_urls> unless absolutely necessary. It triggers manual review and scares users.


Tip 3: The Popup Architecture

Every popup follows this pattern:

popup/
├── popup.html      ← Minimal HTML shell
├── popup.css       ← Styling (inline if small)
└── popup.js        ← All logic here
Enter fullscreen mode Exit fullscreen mode

Keep popups fast. Users expect instant response:

// popup.js
document.addEventListener('DOMContentLoaded', async () => {
  // Load saved state
  const { settings } = await chrome.storage.local.get('settings');

  // Initialize UI
  renderUI(settings || defaultSettings);

  // Bind events
  document.getElementById('save-btn')
    .addEventListener('click', handleSave);
});

async function handleSave() {
  const settings = collectFormData();
  await chrome.storage.local.set({ settings });
  showToast('Saved!');
}
Enter fullscreen mode Exit fullscreen mode

Tip 4: Service Workers Die — Handle It

V3 Service Workers are not persistent. They shut down after ~30 seconds of inactivity. This means:

  • No global variables that persist between events
  • No setInterval() for periodic tasks — use chrome.alarms
  • Always restore state from chrome.storage on wake
// background.js (Service Worker)

// BAD: This variable resets when the worker restarts
let counter = 0;

// GOOD: Persist to storage
chrome.runtime.onMessage.addListener(async (msg) => {
  const { counter } = await chrome.storage.local.get('counter');
  const newCounter = (counter || 0) + 1;
  await chrome.storage.local.set({ counter: newCounter });
});

// BAD: setInterval dies with the worker
setInterval(checkSomething, 60000);

// GOOD: Alarms survive worker restarts
chrome.alarms.create('check', { periodInMinutes: 1 });
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === 'check') checkSomething();
});
Enter fullscreen mode Exit fullscreen mode

Tip 5: Privacy Policy is Required

Chrome Web Store requires a privacy policy URL for any extension that collects data. Even if you don't collect anything, you need one that says so.

I host mine on Vercel as a simple static HTML page:

https://homepage-three-ochre.vercel.app/privacy-policy-[extension-name].html
Enter fullscreen mode Exit fullscreen mode

Template:

<h1>Privacy Policy - [Extension Name]</h1>
<p>This extension does not collect, store, or transmit any personal data.</p>
<p>All data is stored locally on your device using Chrome's storage API.</p>
<p>No analytics, no tracking, no third-party services.</p>
<p>Contact: your-email@example.com</p>
Enter fullscreen mode Exit fullscreen mode

Tip 6: Freemium Model for Chrome Extensions

Free extensions get downloads. But how do you monetize?

My approach — freemium with feature gating:

  1. Core functionality is free forever
  2. Premium features (themes, export, bulk operations) require a one-time payment
  3. Payment verification via a simple license key API

I built a license key validation API on Cloudflare Workers that handles this for all my extensions.


Tip 7: Review Times and Gotchas

Current review timeline (as of March 2026):

  • New submissions: 3-7 business days
  • Updates to existing: 1-3 business days
  • Rejections: Usually permissions-related

Common rejection reasons:

  1. Requesting unnecessary permissions
  2. Missing privacy policy
  3. Misleading description
  4. Code obfuscation (not allowed in V3)

Publishing Checklist

Before submitting to Chrome Web Store:

  • [ ] Manifest V3 with minimum permissions
  • [ ] Icons: 16x16, 48x48, 128x128 PNG
  • [ ] Screenshots: 1280x800 or 640x400 (at least 1)
  • [ ] Privacy policy URL (hosted and accessible)
  • [ ] Description: clear, no keyword stuffing
  • [ ] Test on Chrome stable, beta, and dev channels
  • [ ] No console.log() in production code
  • [ ] Content Security Policy configured

Resources

My extensions: Search "miccho27" on Chrome Web Store (or check back as more get approved)

Other developer tools I've built:

Building in public from Paraguay. Follow for more on Chrome extensions, APIs, and indie development.

Top comments (0)