Making a chrome extension to save bookmarks cross-browser compatible

Codever Logo

(P) Codever is an open source bookmarks and snippets manager for developers & co. See our How To guides to help you get started. Public bookmarks repos on Github ⭐🙏

When I first just published the “Save to” chrome extension in the Chrome Web Store, I did not have the time to develop a version for Firefox, thinking I would need to learn another technology. Recently I developed another extension to Save code snippets to This time I was determined to invest the time to make also Firefox version. As it turns out I had to make little to no changes in code base to make it work both in Chromium based and Firefox browsers. All this with great help from the webextension polyfill the guys from Mozilla created for us.

So, in this blog post we are going to revisit the Save link to extension, and I will detail the changes required to make the extension compatible with Firefox.

The, newly renamed, Save link to browser extension is available for:

Chrome Firefox
Chrome Firefox

Before I do that, let’s have a look at the extension in action, so you know what I am talking about:

Browser extension in action

Right click OR click the extension icon to save the active tab’s link to

Install the polyfill

Since this extension is fairly simple, it doesn’t use a package.json or a webpack bundle, so I needed to download the polyfill script. All the versions released on npm are available for direct download from

and linked to the Github releases

For extensions that already include a package.json file, the last released version of this library can be quickly installed using npm install --save-dev webextension-polyfill

Setup of the polyfill

In order to use the polyfill, it must be loaded into any context where browser APIs are accessed. The most common cases are background and content scripts, which can be specified in manifest.json (make sure to include the browser-polyfill.js script before any other scripts that use it):

  // ...

  "background": {
    "scripts": [

  "content_scripts": [{
    // ...
    "js": [

For HTML documents, such as browserAction popups, or tab pages see the setup section in the project’s README1.

The implementation changes

The implementation uses a background script that will trigger the execution of another javascript, launch-bookmarksdev-dialog.js when clicked on the extension icon or right click and select Save link to Here I only needed to change chrome with browser, so not it looks like this:


function launchBookmarksDevDialog() {
        file: 'launch-bookmarksdev-dialog.js'


browser.runtime.onInstalled.addListener(function () {
        "id": "save-link-to-bookmarksdev",
        "title": "Save link to",
        "contexts": ["all"]

instead of chrome.browserAction...

Test the extension

You can still test the extension locally by loading and reloading the sources either in Chrome or Firefox, but with the help web-ext2 things have gotten easier.

Just run the following command in the project root directory

web-ext run

This will start Firefox with the extension installed and reloads it when you do changes in the source code. For options see web-ext command reference.3>

Build the extension

Packaging the extension for release has also gotten easier with the help of web-ext utility.

If before I would use a zip command

zip -r * -x *.idea* *.git* '*resources/*' '*assets/*' "**" "**" '*web-ext-artifacts/*'

now I use the web-ext build command

web-ext build --overwrite-dest -i 'resources' 'assets' '' ''

This packages an extension into a .zip file, ignoring files that are commonly unwanted in packages, such as .git and other artifacts. The name of the .zip file is taken from the name field in the extension manifest.

You can still exclude files by yourself, as seen above with the help of the -ioption. See the command reference3 for further options.


In this post you’ve seen a way how to migrate your Chrome Extension to be compatible with Firefox with the help of webextension polyfill.

If you have found this useful, please show some love and give us a star on Github


Subscribe to our newsletter for more code resources and news

Adrian Matei (aka adixchen)

Adrian Matei (aka adixchen)
Life force expressing itself as a coding capable human being

routerLink with query params in Angular html template

routerLink with query params in Angular html template code snippet Continue reading