Most of the extension ideas we hear should start life as a web app. Not because extensions are bad, but because an extension is the harder product to build, ship and change, and people reach for it when a link to a website would have done the job.
Where an extension is the right answer, it is very right. So this post is an argument with an escape hatch: a short case for starting with a web app, then a five-question test that tells you when to ignore us and build the extension.
The case for a web app first
A web app is a link. You send it, someone opens it, they're in. An extension is a store listing, an install click and a permission prompt that reads, in Chrome's own blunt words, what your code will be able to see. Every one of those steps loses people, and the permission prompt loses the careful ones, who are often the buyers you want.
Then there is change. A web app changes when you deploy. An extension changes when the store approves the new version, because Manifest V3, the only version Chrome accepts for new items, does not let an extension download and run new code. Settings and data can come from your server. Logic can't. So if you are still finding out what the product is, every experiment pays a review toll.
And there are the phones. Chrome on Android and iPhone does not run extensions. If your users do their work on a phone, an extension doesn't reach them at all.
None of this is fatal. It just means an extension has to earn its extra cost, and plenty of ideas don't.
When the extension earns it
There is one thing an extension does that nothing else can. It sits beside every tab, and with permission it can read and add to the page the user already has open. The whole reason to build one is that the user doesn't have to leave where they are.
That matters when the work happens inside someone else's software. A CRM, a job board, a marketplace seller panel, a government portal, an email inbox. You can't change those sites. You can't ask your users to stop using them. You can only meet them there. If the alternative is copy, switch tab, paste, switch back, forty times a day, the extension's install friction is a small price.
An extension with a companion web app is a shape we have built before, and the Copilotly case study tells that story in its own words.
The five-question test
Answer these about one real task, not the product in general.
- Is the thing you help with on a page you don't own? If the work happens in your own product, build the web app. Stop here.
- Does the user leave that page to use you today? Watch someone do the task for twenty minutes and count the trips to another tab. A handful an hour is a real cost. Once a week isn't.
- Are they at a desktop? If the honest answer is "mostly on phones", an extension misses most of them.
- Can you name the sites? "This one CRM and that one marketplace" gives a narrow permission and an install warning that names those sites, which a company's IT team can approve. "Every site, always" gives a warning that scares people and draws closer review.
- Does the other tool have a usable API or app marketplace? If it does, an integration through that third-party API may put your feature in front of every user of the tool with no install in each browser. It depends on what the other company allows, and how stable its API is, but check before you build around its page structure.
Yes, yes, yes, yes, no: build the extension. Anything else, and the web app or the integration is probably the better first product. You can add the extension later as a shortcut, and many good products end up with both.
If you build it, keep it small
The extensions that work best are thin. The popup or side panel does the job on the page; everything heavy lives in a web app behind it. Sign-up, billing, settings, history and team management belong there, partly because they are easier to build as ordinary pages, and partly because the Chrome Web Store no longer processes payments for extensions. A paid extension charges through its own web app, and the extension asks your server what plan the user is on. Billing then works like any subscription billing setup, the same way we wire Stripe payments into any SaaS product.
The web app does one more job people forget: it gives search engines something to index. A store listing ranks for very little. A site with a page per use case can.
Permissions are where most extensions lose installs, so we write the one-sentence purpose and the justification for each permission before we write code. activeTab gives access to the current page only when the user clicks, and adds no install warning, which covers most assistants and clippers. Anything that needs more asks for an optional permission at the moment the feature is turned on, with an explanation in your own words. The principle is plain least privilege: every permission you don't request is a risk you don't carry and a sentence in the prompt nobody has to read.
The security rules we don't bend
An extension runs next to your users' email, their bank and their company's tools. That neighbourhood deserves care.
Nothing secret goes in the package. Anyone who installs an extension can unpack it and read every file, so API keys stay on the server and the extension holds only a short-lived token for the signed-in user. Our secrets management entry has the longer version.
Page text is untrusted. A content script reads pages other people wrote, and those pages can contain markup or instructions aimed at your extension. If page text goes to an AI model, that is prompt injection waiting to happen. We treat it as data, never insert it into the panel as raw HTML, and validate it again on the server.
The parts talk in typed messages. The page, the panel, the background service worker and your server each run in a different place with different rules, and most extension bugs live in the gaps between them. Every message has a name and a defined shape in TypeScript, so a change on one side fails the build instead of failing quietly in a user's browser. And because Chrome stops the service worker when it's idle, nothing important is held in memory.
Living with other people's websites
The awkward truth about an extension is that its most important dependency is a site you don't control. When the CRM redesigns, your content script can break overnight, and nobody will warn you.
So the script depends on as little page structure as it can, and when the page isn't what it expects, it fails quietly, says so and offers a manual path, rather than doing something wrong. Content scripts get tested on the real sites, signed in, on slow connections. Error monitoring tells us which sites and versions are failing, usually before a user writes in. Chrome ships a new version every four weeks, and the sites change on their own schedule, so an extension needs maintenance from the day it ships.
Edge and Brave run the same build; Firefox needs testing and some code of its own. We decide the browser list in week one, because it changes which APIs we can use. For a staff tool you can skip the public store entirely: unlisted for pilots, or installed by company policy on managed browsers.
If the extension calls AI
Then the extension itself costs almost nothing to distribute, and the bill sits in your backend, where every click can cost money. Meter every call from the first day and set daily limits per plan from measured costs. We wrote up how we did that for an app in what an AI plant scan costs; the same method applies to a side panel.
Where to start
If the test said web app, our web app development page is the better door, and the SaaS platforms page covers accounts and billing. If it said extension, the Chrome extension development page lays out the parts, the permissions and the review. Either way, a Discovery Sprint settles the shape with a clickable prototype of the panel and a fixed price, before you have paid for a single store submission.
