Packaging One Browser Extension for Chrome and Firefox
Table of Contents
Why I started #
Reddit can show an official translated version of a post when one is available. I did not want to build another translation engine. I only wanted a quicker way to choose a language and turn translation on or off.
I started a small extension with a language selector and an enable/disable toggle. The first structure targeted Chrome. Firefox support came after the basic flow was in place.
Splitting the responsibilities #
The extension uses Manifest V3 and has four main parts.
popup/*: UI for selecting a language and enabling translationbackground.js: entry point for the background script/service workercontent-scripts/content.js: content script that runs on Reddit pagesmanifest.json: permissions, scripts, and extension metadata
The popup only collects the user’s settings. I connected those settings to the content script and prepared the link modification flow there.
I checked this connection before adding more options. Keeping the boundary small made it easier to see which part needed to change next.
Packaging the same source twice #
I did not keep a separate copy of the source for Firefox. Common behaviour stays in one place, while browser-specific differences are applied during packaging.
I updated the manifest version and author, added the Firefox settings, and used package.sh to create the browser-specific outputs.
The extension also runs code in several places. I added a configurable logging utility so logs from the popup, background, and content script could be enabled only when needed.
Work after the feature #
Code running locally did not mean the extension was ready to share.
I arranged the icons and manifest metadata, then documented the install and build steps. I also added PRIVACY_POLICY.md to describe how the extension handles data.
This was packaging preparation, not a claim that the extension had already been published to browser stores. The scope was to make Chrome and Firefox packages repeatable and leave the required documentation with them.
What I learned #
The language selector was simpler than deciding how to deliver one source to two browsers. For the next small extension, I will check manifest differences, packaging, and documentation at the beginning instead of leaving them until the feature is finished.