DEV Community

sheep
sheep

Posted on

2 1 1

Chrome Extension Development: Which Implementation Fits Your Needs

There are several ways to build a Chrome extension, each with distinct capabilities. which approach would you choose?

Before start

Every Chrome extension starts with a manifest.json file, which serves as the blueprint for the extension. This file defines essential metadata such as the extension’s name, version, permissions, and the scripts or pages it will use. 

According to the official announcement from Chrome for Developers, starting from June 2025 with Chrome version 139, only Manifest V3 will be supported, while Manifest V2 will be phased out.

We will explore the whole way based on the Manifest V3 standard. Let's go!

1. Popup

One of the most common ways to interact with an extension is through a popup that appears when the user clicks the extension icon in the toolbar. This popup is a small HTML page defined in the manifest and typically contains a simple interface for quick interactions.

directory structure :

popup
├── icon.png
├── manifest.json
└── popup.html
Enter fullscreen mode Exit fullscreen mode

manifest.json

{
  "manifest_version": 3,
  "version": "0.0.1",
  "name": "my-extension",
  "description": "describe here",
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icon.png"
  }
}
Enter fullscreen mode Exit fullscreen mode

In manifest.json, in addition to specifying the extension's version, name, and description, it also configures the popup's HTML file (popup.html) through the action.default_popup field and the toolbar icon via action.default_icon.

popup.html

<!DOCTYPE html>
<html>
<body>
  <div style="padding: 16px">
    <h3>My Extension</h3>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The popup.html forms the foundation of its user interface, it may contain references to supporting CSS and JavaScript files that together enable the extension's functionality and interactivity.

interaction:
Click the extension's toolbar icon, its popup interface will appear.

Image description

2. New Tab

Instead of a popup, some extensions may prefer to open a full tab when clicked. This approach is useful when the extension requires more space for complex interactions.

To achieve this, the extension can listen for clicks on the browser action and then programmatically open a new tab. The background.js script handles this logic.

directory structure:

newtab
├── background.js
├── icon.png
├── index.html
└── manifest.json
Enter fullscreen mode Exit fullscreen mode

manifest.json

{
  "manifest_version": 3,
  "version": "0.0.1",
  "name": "my-extension",
  "description": "describe here",
  "action": {
    "default_icon": "icon.png"
  },
  "background": {
    "service_worker": "/background.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

In manifest.json, background.js is specified by the background.service_worker field.

background.js

chrome.action.onClicked.addListener(function(tab) {
  chrome.tabs.create({'url': chrome.runtime.getURL('index.html')}, 
  function(tab) {
    // Tab opened.
  });
});
Enter fullscreen mode Exit fullscreen mode

In background.js, it listens for click events on the icon and invokes the api of chrome.tabs.create to open a new tab. The new tab's URL is generated using chrome.runtime.getURL('index.html'), which automatically resolves the full extension-relative path for the specified HTML file (index.html).

index.html

<!DOCTYPE html>
<html>
<body>
  <div style="padding: 16px">
    <h3>index page</h3>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.html can accommodate significantly more content than the popup window since it functions as a complete standalone page, offering full flexibility for your implementation needs.

interaction:
Click the toolbar icon to open a new tab.

Image description

3. Sidebar

Chrome also supports a less common but interesting option: the sidebar (or side panel). This opens a vertical panel next to the current webpage, perfect for tools that need to stay visible while browsing — like document outlines or live translators.

To use a sidebar, the manifest.json needs the "sidePanel" permission, and the extension controls it using the chrome.sidebarAction API. Unlike popups, sidebar stay open until the user closes them, making them great for long-term tasks.

directory structure:

sidebar
├── background.js
├── icon.png
├── manifest.json
└── side_panel.html
Enter fullscreen mode Exit fullscreen mode

manifest.json

{
  "manifest_version": 3,
  "version": "0.0.1",
  "name": "plugin-test",
  "description": "describe here",
  "side_panel": {
    "default_path": "side_panel.html"
  },
  "action": {
    "default_icon": "icon.png"
  },
  "background": {
    "service_worker": "/background.js"
  },
  "permissions": [
    "sidePanel"
  ]
}
Enter fullscreen mode Exit fullscreen mode

In manifest.json, the sidebar's HTML file (side_panel.html) is declared through the side_panel.default_path field. Additionally, the "sidePanel" permission must be included in the permissions array to enable sidebar functionality.

background.js

chrome.sidePanel
  .setPanelBehavior({ openPanelOnActionClick: true })
  .catch((error) => console.error(error));
Enter fullscreen mode Exit fullscreen mode

Click events will be listened from background.js to control the sidebar.

side_panel.html

<!DOCTYPE html>
<html>
<body>
  <div style="padding: 16px">
    <h3>side panel</h3>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

side_panel.html can be utilized much like a full tab page, with both providing sufficient possibility for feature-rich interfaces.

interaction:
Click the toolbar icon to toggle the sidebar open and closed.

Image description

4. Embedding Widget

Some extensions modify web pages by embedding small interactive widgets directly into them. Content scripts can add floating toolbars or translation bubbles by modifying current page’s DOM. These scripts run inside the webpage but can’t use most Chrome extension APIs due to security restrictions.

directory structure:

widget
├── manifest.json
└── widget.js
Enter fullscreen mode Exit fullscreen mode

manifest.json

{
  "manifest_version": 3,
  "version": "0.0.1",
  "name": "my-extension",
  "description": "describe here",
  "content_scripts": [
    {
      "matches": ["https://test.com/*"],
      "js": ["widget.js"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The content_scripts field in manifest.json defines which scripts get injected into matching web pages, specifying the JavaScript (or CSS) files to inject and the URL patterns that determine when injection occurs.

widget.js

const widget = document.createElement('div');
widget.id = 'extensionWidget';
widget.style.position = 'fixed';
widget.style.top = '15px';
widget.style.right = '160px';
widget.style.padding = '10px';
widget.style.background = 'blue';
widget.style.borderRadius = '8px';
widget.style.zIndex = '9999';

widget.innerHTML = `<h4 style="color: white">Extension Widget</h4>`;
document.body.appendChild(widget);

Enter fullscreen mode Exit fullscreen mode

Once the extension is installed and enabled, widget.js will be injected and executed in all pages matching the https://test.com/* URL pattern, and the "Extension Widget" widget will be displayed on the top-right corner.

Image description

This method allows for seamless integration with web pages but requires careful handling of existing page elements to avoid conflicts.

Summary

Each approach has its use cases - popups for quick interactions, new tabs for complex UIs, injected sidebars for persistent tools, and embedded widgets for page integration. The best choice depends on your extension's specific requirements and user experience goals.

Remember to always request the minimal necessary permissions and test your extension thoroughly, as Manifest V3 has stricter security requirements than its predecessor.


I just developed a Chrome extension called Bookmark Dashboard, a bookmark management tool, and I’d love to share it with fellow bookmark enthusiasts!

Thanks for reading!

Tiger Data image

🐯 🚀 Timescale is now TigerData

Building the modern PostgreSQL for the analytical and agentic era.

Read more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Explore this insightful write-up embraced by the inclusive DEV Community. Tech enthusiasts of all skill levels can contribute insights and expand our shared knowledge.

Spreading a simple "thank you" uplifts creators—let them know your thoughts in the discussion below!

At DEV, collaborative learning fuels growth and forges stronger connections. If this piece resonated with you, a brief note of thanks goes a long way.

Okay