From 4d817ea93271ccdc38b94a7585c8027c9feb0532 Mon Sep 17 00:00:00 2001 From: Bernd Rodler Date: Tue, 4 Aug 2026 12:54:43 +0200 Subject: [PATCH] feat(electron): packaging targets - mac/win/linux, unsigned Phase 1 step 6 of VNCprodbuild. electron-builder.config.js now has real targets: mac (dmg, zip; x64+arm64), Windows (nsis; x64), Linux (AppImage, deb; x64). Still no code signing (step 9 - needs an Apple Developer ID and optionally a Windows cert, both human-owned purchases). Icon wired from public/icon-512x512.png (the existing PWA manifest icon) - electron-builder generates .icns/.ico from it automatically. This is a stand-in, not a dedicated app icon: it's only 512x512 (the macOS icns's largest slot wants 1024x1024+), and public/branding/Bulwark_Icon_App.svg looks like the actual intended master for this, but it's a vector file and this environment has no SVG rasterizer (rsvg-convert/ImageMagick/Inkscape) to export it at high res. Flagged in the config's comments; someone with the right tooling (or a designer) should export that SVG at 1024x1024+ and swap the `icon` path. Caught and fixed a real bug by actually running a --dir build rather than just trusting the config: app-builder-lib's extraResources copy unconditionally drops any directory literally named "node_modules" sitting at the copy root (node_modules/app-builder-lib/out/util/filter.js), so the naive `from: ".next/standalone"` silently stripped the standalone server's own node_modules and the packaged app crashed with "Cannot find module 'next'" on launch. Fixed by copying from one level up (`from: ".next"` with a `standalone/**/*` filter) so "node_modules" is never the literal copy root. Verified by launching the packaged --dir mac build directly - it boots the standalone server and serves the app with no errors, same as the unpackaged dev flow. --- electron-builder.config.js | 75 ++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/electron-builder.config.js b/electron-builder.config.js index 108bde32..4638e607 100644 --- a/electron-builder.config.js +++ b/electron-builder.config.js @@ -1,12 +1,17 @@ -// Base electron-builder config - Phase 1 step 1 of the VNCprodbuild rollout. -// No code signing and no platform targets configured yet; this exists only -// to prove the packaging concept end to end (the app runs, boots its own -// server, opens a window). Targets (dmg/zip/nsis/AppImage/deb), branding -// icons, and code signing are wired up in later steps - see -// ~/.claude/skills/VNCprodbuild/SKILL.md, Phase 1 steps 6-9. +// electron-builder config for the VNCmail+ (Bulwark) desktop shell. +// +// Phase 1 of the VNCprodbuild rollout (~/.claude/skills/VNCprodbuild/SKILL.md): +// step 1 - base config, no targets (superseded by this file) +// step 6 - this file: real packaging targets + branding icon (below) +// step 7 - electron-updater wiring (GitHub Releases feed) - adds a +// `publish` block on top of this file in a later commit. +// step 9 - still open: code signing / notarization (Apple Developer ID, +// optional Windows cert) - both are human-owned purchases, not +// configured here. Builds below ship UNSIGNED. module.exports = { appId: "de.vnc.vncmailplus", productName: "VNCmail+", + copyright: "Copyright © VNC AG", directories: { output: "dist-electron-builds", }, @@ -16,8 +21,62 @@ module.exports = { // Same artifact the Dockerfile bakes into the container image (see // Dockerfile + scripts/assemble-standalone.mjs). electron/main.ts // reads it from process.resourcesPath in packaged builds. - from: ".next/standalone", - to: "standalone", + // + // Deliberately `from: ".next"` (not ".next/standalone") + a filter, + // not the more obvious `from: ".next/standalone"` alone: + // app-builder-lib's copy filter unconditionally drops a directory + // literally named "node_modules" sitting at the copy root (see + // node_modules/app-builder-lib/out/util/filter.js's + // `relative === "node_modules"` check - it assumes extraResources are + // hand-authored assets, not a pre-built server with a traced + // node_modules of its own). Copying from one level up so + // "standalone/node_modules" is never the literal copy root sidesteps + // that check, so the standalone server's node_modules actually + // survives into the packaged app instead of getting silently + // stripped (caught by manually launching a --dir build - the packaged + // server crashed with "Cannot find module 'next'"). + from: ".next", + filter: ["standalone/**/*"], + to: ".", }, ], + // STAND-IN ICON, not a dedicated app icon: public/icon-512x512.png is the + // PWA manifest icon (512x512 square PNG). electron-builder can generate + // .icns/.ico from a single square PNG at build time (see + // node_modules/app-builder-lib/out/util/iconConverter.js), so this + // produces working icons for every target below - but at only 512x512, + // the largest macOS icns representation (1024x1024 "ICON512@2x") gets + // upsampled and will look soft compared to a real 1024x1024+ source. + // public/branding/Bulwark_Icon_App.svg looks like the intended master for + // this (as opposed to Bulwark_Favicon.png, sized for browser tabs), but + // it's vector and this environment has no SVG rasterizer (rsvg-convert / + // ImageMagick / Inkscape) to turn it into a proper 1024x1024 PNG. A human + // (or a follow-up step with the right tooling) should export + // Bulwark_Icon_App.svg at 1024x1024 and point `icon` at that instead. + icon: "public/icon-512x512.png", + mac: { + target: [ + { target: "dmg", arch: ["x64", "arm64"] }, + { target: "zip", arch: ["x64", "arm64"] }, + ], + category: "public.app-category.productivity", + // No Apple Developer ID yet (VNCprodbuild step 9) - ship unsigned/ + // un-notarized for now. hardenedRuntime is meaningless without signing + // but left explicit so it's obvious what step 9 needs to flip on. + hardenedRuntime: false, + }, + win: { + target: [{ target: "nsis", arch: ["x64"] }], + }, + nsis: { + oneClick: false, + allowToChangeInstallationDirectory: true, + }, + linux: { + target: [ + { target: "AppImage", arch: ["x64"] }, + { target: "deb", arch: ["x64"] }, + ], + category: "Network;Email;", + }, };