CrowdAssist is compatible with both Chrome and Firefox using a single codebase with separate manifest files for each browser.
- Ensure Chrome manifest is active:
./switch-manifest.sh chrome
- Open
chrome://extensions/(or equivalent) - Enable "Developer mode"
- Click "Load unpacked"
- Select the
extension/folder
- Switch to Firefox manifest:
./switch-manifest.sh firefox
- Open
about:debugging#/runtime/this-firefox - Click "Load Temporary Add-on"
- Navigate to the
extension/folder and selectmanifest.json
Key Point: Firefox always reads the file named
manifest.json, which is why we use a switch script to swap between the Chrome and Firefox versions.
While both browsers support web extensions, they have different manifest requirements:
| Feature | Chrome (MV3) | Firefox (MV2) |
|---|---|---|
| Manifest Version | 3 | 2 (more stable) |
| Background Script | service_worker |
scripts |
| Popup Action | action |
browser_action |
| Permissions | Separate host_permissions |
Combined in permissions |
| Web Resources | Object format | Array format |
The JavaScript code is identical - only the manifest configuration differs.
All JavaScript files include a compatibility shim at the top:
// Browser API compatibility shim for Chrome and Firefox
if (typeof browser === 'undefined') {
var browser = chrome;
}This ensures seamless API compatibility:
- Firefox: Natively uses
browser.*API (returns Promises) - Chrome: Uses
chrome.*API, polyfill providesbrowser.*wrapper
Use the provided script to switch between browser manifests:
# Switch to Firefox manifest (Manifest V2)
./switch-manifest.sh firefox
# Switch back to Chrome manifest (Manifest V3)
./switch-manifest.sh chromeThe script:
- Backs up the current
manifest.jsonasmanifest.chrome.json - Copies
manifest.firefox.jsontomanifest.json(or vice versa) - Ensures you're always using the correct manifest for your target browser
Chrome:
./switch-manifest.sh chrome
# Then reload the extension in chrome://extensionsFirefox:
./switch-manifest.sh firefox
# Then remove and re-add the extension in about:debuggingCheck which manifest is currently active:
# Check manifest version
grep "manifest_version" extension/manifest.json
# If it shows "2" → Firefox manifest
# If it shows "3" → Chrome manifest- Create a ZIP file with the
extension/folder contents - Exclude
manifest.firefox.jsonfrom the package - Include only
manifest.json(MV3 with service_worker)
cd extension
zip -r ../crowdassist-chrome.zip . -x "manifest.firefox.json"- Create a ZIP file with the
extension/folder contents - Rename
manifest.firefox.jsontomanifest.jsonbefore packaging - Or use a build script to swap manifests automatically
cd extension
cp manifest.firefox.json manifest.json
zip -r ../crowdassist-firefox.zip .
git restore manifest.json # restore originalYou can create a simple build script to automate packaging:
#!/bin/bash
# Build for Chrome
cd extension
zip -r ../dist/crowdassist-chrome.zip . -x "manifest.firefox.json"
# Build for Firefox
cp manifest.firefox.json manifest.json
zip -r ../dist/crowdassist-firefox.zip .
git restore manifest.json
echo "✅ Built packages for both browsers in dist/"Chrome MV3 requires service workers:
- Event-driven, non-persistent background script
- More resource efficient
- Required for Chrome Web Store submissions
Firefox MV2 uses traditional background scripts:
- More stable and mature implementation
- Firefox MV3 service worker support is still experimental
- Fully compatible with all Firefox versions 91+
Both approaches work identically from the extension's perspective thanks to the browser API polyfill.
This means Firefox tried to use the Chrome manifest. Solution:
- Make sure to select
manifest.firefox.jsonwhen loading - If you see this error, remove the extension and re-add it
This means Chrome tried to use the Firefox manifest. Solution:
- Chrome automatically uses
manifest.jsonfrom the folder - Make sure
manifest.jsoncontainsservice_worker, notscripts
Check that the browser polyfill is present at the top of each JS file:
background.jscontent.jspopup.js