Skip to content

Commit b81a8ba

Browse files
vveerrggclaude
andcommitted
feat: add Firefox build target
Firefox MV3 manifest with background scripts (not service worker), popup-based UI, and gecko extension ID. Builds to distros/firefox/ with zip for AMO upload. - New: src/firefox-manifest.json - New: npm run build:firefox / build:firefox:prod - Updated: build:all now includes Firefox - Minimum Firefox version: 109.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1810a3e commit b81a8ba

3 files changed

Lines changed: 93 additions & 0 deletions

File tree

build.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const target = process.argv[3] || 'safari'; // safari | chrome | all
1111
const SRC = './src';
1212
const SAFARI_DIST = './distros/safari';
1313
const CHROME_DIST = './distros/chrome';
14+
const FIREFOX_DIST = './distros/firefox';
1415

1516
const entryPoints = {
1617
'background.build': `${SRC}/background.js`,
@@ -178,6 +179,33 @@ async function buildChrome(opts = {}) {
178179
console.log(`Chrome zip → ./distros/${zipName}`);
179180
}
180181

182+
// ---------------------------------------------------------------------------
183+
// Firefox build — bundles to distros/firefox/ with the Firefox manifest
184+
// ---------------------------------------------------------------------------
185+
async function buildFirefox(opts = {}) {
186+
await esbuild.build({
187+
...shared,
188+
...opts,
189+
entryPoints,
190+
outdir: FIREFOX_DIST,
191+
});
192+
193+
copyStaticAssets(FIREFOX_DIST);
194+
195+
// Firefox-specific manifest
196+
fs.copyFileSync(path.join(SRC, 'firefox-manifest.json'), path.join(FIREFOX_DIST, 'manifest.json'));
197+
198+
// Zip for AMO upload
199+
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
200+
const zipName = `nostrkey-firefox-v${pkg.version}.zip`;
201+
const zipPath = path.join('./distros', zipName);
202+
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
203+
execSync(`cd ${FIREFOX_DIST} && zip -r ../${zipName} . -x '.*'`);
204+
205+
console.log(`Firefox build complete → ${FIREFOX_DIST}/`);
206+
console.log(`Firefox zip → ./distros/${zipName}`);
207+
}
208+
181209
// ---------------------------------------------------------------------------
182210
// Main
183211
// ---------------------------------------------------------------------------
@@ -206,8 +234,11 @@ async function run() {
206234
if (target === 'all') {
207235
await buildSafari(buildOpts);
208236
await buildChrome(buildOpts);
237+
await buildFirefox(buildOpts);
209238
} else if (target === 'chrome') {
210239
await buildChrome(buildOpts);
240+
} else if (target === 'firefox') {
241+
await buildFirefox(buildOpts);
211242
} else {
212243
// default: safari
213244
await buildSafari(buildOpts);

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
"build:prod": "tailwindcss -i './src/options.css' -o './src/options.build.css' --minify && ./build.js prod",
1414
"build:chrome": "tailwindcss -i './src/options.css' -o './src/options.build.css' && ./build.js dev chrome",
1515
"build:chrome:prod": "tailwindcss -i './src/options.css' -o './src/options.build.css' --minify && ./build.js prod chrome",
16+
"build:firefox": "tailwindcss -i './src/options.css' -o './src/options.build.css' && ./build.js dev firefox",
17+
"build:firefox:prod": "tailwindcss -i './src/options.css' -o './src/options.build.css' --minify && ./build.js prod firefox",
1618
"build:all": "tailwindcss -i './src/options.css' -o './src/options.build.css' && ./build.js dev all",
1719
"build:all:prod": "tailwindcss -i './src/options.css' -o './src/options.build.css' --minify && ./build.js prod all",
1820
"watch": "./build.js watch",

src/firefox-manifest.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"manifest_version": 3,
3+
"default_locale": "en",
4+
"name": "__MSG_extension_name__",
5+
"description": "__MSG_extension_description__",
6+
"version": "1.5.7",
7+
"short_name": "NostrKey",
8+
"author": "Humanjava Enterprises Inc",
9+
"homepage_url": "https://nostrkey.com",
10+
"icons": {
11+
"16": "images/toolbar-16.png",
12+
"48": "images/icon-48.png",
13+
"96": "images/icon-96.png",
14+
"128": "images/icon-128.png",
15+
"256": "images/icon-256.png",
16+
"512": "images/icon-512.png"
17+
},
18+
"background": {
19+
"scripts": ["background.build.js"]
20+
},
21+
"content_scripts": [
22+
{
23+
"js": ["content.build.js"],
24+
"matches": ["<all_urls>"]
25+
}
26+
],
27+
"action": {
28+
"default_title": "Open NostrKey",
29+
"default_popup": "sidepanel.html",
30+
"default_icon": {
31+
"16": "images/toolbar-16.png",
32+
"19": "images/toolbar-19.png",
33+
"32": "images/toolbar-32.png",
34+
"38": "images/toolbar-38.png",
35+
"48": "images/toolbar-48.png",
36+
"72": "images/toolbar-72.png"
37+
}
38+
},
39+
"options_ui": {
40+
"page": "full_settings.html",
41+
"open_in_tab": true
42+
},
43+
"permissions": ["storage", "clipboardWrite"],
44+
"host_permissions": ["<all_urls>"],
45+
"web_accessible_resources": [
46+
{
47+
"resources": ["nostr.build.js"],
48+
"matches": ["<all_urls>"]
49+
}
50+
],
51+
"content_security_policy": {
52+
"extension_pages": "script-src 'self'; object-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' wss://*; frame-src 'self'; font-src 'self'; media-src 'self'; child-src 'self';"
53+
},
54+
"browser_specific_settings": {
55+
"gecko": {
56+
"id": "nostrkey@nostrkey.com",
57+
"strict_min_version": "109.0"
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)