
7 min read
From the studio
We build apps people actually keep.Tinkrd is a small indie studio making focused, high-quality apps for everyday life. See what we're working on.
View our appsCreating a Chrome plugin is one of those projects that sounds complicated but is genuinely approachable once you understand the four or five moving pieces. The Chrome extension platform uses standard web technologies, so if you know HTML, CSS, and a little JavaScript, you already have most of what you need. This guide walks through the real process, not the sanitized version.
What a Chrome Plugin Actually Is
A Chrome plugin (Google’s official term is “Chrome extension”) is a small web app that runs inside the Chrome browser and gets access to browser APIs that normal web pages cannot touch. It can read and modify page content, intercept network requests, add toolbar buttons, or open side panels. The browser loads it from a local folder or from the Chrome Web Store.
Every extension is built from three core layers:
- A manifest file that tells Chrome what the extension is and what permissions it needs.
- Background scripts (called service workers in Manifest V3) that run in the background, outside any tab.
- Content scripts that inject JavaScript directly into web pages.
That structure is the same whether you are building a simple color-picker or a full productivity tool. Understanding it early saves you a lot of confusion later. For a broader look at the craft side of this work, the Chrome extension development guide is worth reading before you write your first line.
Setting Up Your Manifest File
The manifest.json file is the entry point for any Chrome extension. Chrome reads it first, and everything else flows from what you declare there. Use Manifest V3, which is the current standard. Manifest V2 is being phased out.
Here is a minimal but real manifest for a simple extension:
{
"manifest_version": 3,
"name": "My First Extension",
"version": "1.0",
"description": "Does one thing well.",
"permissions": ["activeTab", "scripting"],
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": [""],
"js": ["content.js"]
}
]
}
Keep permissions to the minimum you actually need. Requesting broad permissions like "tabs" or "webRequest" triggers extra scrutiny during Chrome Web Store review, and it erodes user trust.
Writing Content Scripts and Background Workers
Content scripts run inside the context of a web page, and background service workers run in a separate, persistent-free context. They communicate by passing messages.
Content scripts
A content script can read and change the DOM of any page it is injected into. Use it to highlight text, add buttons, or scrape data from a page the user is already viewing.
// content.js
document.body.style.backgroundColor = 'lightyellow';
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'GET_TITLE') {
sendResponse({ title: document.title });
}
});
Background service workers
The service worker handles events like toolbar clicks, alarm timers, and responses from external APIs. It cannot access the DOM. It wakes on demand and can sleep between tasks, so do not rely on it to hold state in memory.
// background.js
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['content.js']
});
});
Message passing between the two is simple. Use chrome.runtime.sendMessage from the content script and chrome.runtime.onMessage in the worker to connect them.
Tools and Stack Options
You do not need a framework to create a Chrome plugin, but for anything beyond a toy project, the right tooling saves real time. Here is an honest comparison of the common approaches:
| Approach | Best for | Build overhead | Cost |
|---|---|---|---|
| Vanilla JS + no bundler | Simple, single-purpose tools | None | Free |
| Vite + vanilla | Multi-file projects, fast reload | Low | Free |
| Plasmo framework | React-based extensions, teams | Medium | Free (open source) |
| CRXJS + Vite | React or Vue with HMR | Medium | Free |
At Tinkrd, we default to the smallest setup that fits the job. For a two-person team, complexity is expensive. Start with vanilla JavaScript and add a bundler only when the file count makes it painful to manage manually.
The full build and publish walkthrough covers the Vite setup in more detail if you want a concrete starting point.
Loading Locally and Testing Your Extension
You can load and test your extension without publishing it. Chrome supports unpacked extensions in developer mode, which is the fastest feedback loop while you build.
- Open Chrome and go to
chrome://extensions. - Toggle on Developer mode in the top right corner.
- Click Load unpacked and select your project folder.
- Your extension appears in the list. Click the puzzle icon in the toolbar to find it.
Every time you change a file, click the refresh icon next to your extension in the list. Content script changes also require a hard reload of the page you are testing on. This trips up almost everyone the first time.
Use console.log freely. For content script logs, open DevTools on the page itself. For background worker logs, click “Service Worker” in the extensions panel to open its dedicated DevTools window.
Publishing to the Chrome Web Store
Publishing requires a one-time $5 developer registration fee with Google. After that, you submit a ZIP of your extension folder through the Chrome Web Store Developer Dashboard. Review typically takes a few days, sometimes longer if permissions look unusual.
A few things that slow down or block approval:
- Requesting permissions you do not actually use in the code.
- Missing a clear privacy policy if you collect any user data.
- Vague descriptions that do not explain what the extension does.
- Icons that are blurry or do not meet the size requirements (16, 48, and 128px).
Write your store listing like you are explaining the extension to a person, not optimizing it for a search algorithm. Clear beats clever.
Frequently asked questions
Do I need to know a specific programming language to create a Chrome plugin?
JavaScript is the primary language for Chrome extension development. HTML and CSS handle any visible UI, like a popup or options page. You do not need TypeScript, but it helps catch errors early on larger projects.
How long does it take to build a basic Chrome extension?
A simple extension that does one thing, like copying text or changing page styles, can be built and loaded locally in a few hours. A polished, publishable extension with a popup UI and settings usually takes a few days to a couple of weeks, depending on scope.
Is creating a Chrome plugin free?
Building is completely free. The only cost is the one-time $5 Google developer account fee required to publish to the Chrome Web Store. Hosting and distribution are handled by Google after that.
Can I use React or another framework inside a Chrome extension?
Yes. React, Vue, and Svelte all work inside extension popups and options pages. You will need a bundler like Vite to compile them. Tools like Plasmo or CRXJS handle most of the configuration for you.
What is the difference between Manifest V2 and Manifest V3?
Manifest V3 replaced V2 as the required standard. The biggest change is that background pages became service workers, which do not persist in memory. V2 extensions still run in some Chrome versions, but Google is actively removing support, so all new extensions should use V3.
Creating a Chrome plugin is one of the more rewarding small software projects you can take on, because the feedback loop is fast and the distribution is built in. Start small, keep permissions lean, and test locally before worrying about publishing. The fundamentals carry you most of the way.
We’re building in the open
Tinkrd is a small studio making thoughtful apps for families. Our first app is launching soon.