fix(electron): real VNCmail+ branding, not just a rename

Every prior distributable DMG this session was built with plain `npx
electron-builder`, never `--config electron-builder.config.js`. electron-
builder does not auto-detect a file named electron-builder.config.js (its
search list is .yml/.yaml/.json/.json5/.js/.cjs/.mjs/.ts, not .config.js),
so the config - correct productName/appId/icon and all - was silently
ignored on every build. Caught only by actually launching the packaged
.app: it booted to "Bulwark Webmail Setup" demanding a token from
container logs, default Electron atom icon, output in dist/ instead of
dist-electron-builds/.

Fixes, each verified against the packaged .app (Playwright _electron.launch,
not the build log):
- Add dist:mac/win/linux/dir scripts that pass --config explicitly, so this
  can't recur.
- Dedicated 1024x1024 app icon (build-resources/app-icon.png, SRC symbol on
  #09090b) instead of reusing the web PWA manifest icon. Verified: icns
  ships at 1024x1024, pixel-identical to the source (mean diff 0.0/255).
- electron/main.ts: getDesktopDefaults() sets JMAP_SERVER_URL to the sandbox
  (the ONLY thing that puts the server into "env-managed" mode and skips
  the setup wizard - see lib/setup/state.ts), plus APP_NAME/login logo/
  favicon/company-name env vars, spread before ...process.env so a real
  deployment still overrides. Verified: packaged app now opens straight to
  a login screen with the JMAP endpoint field pre-filled
  https://stalwart.sandbox.vnc.de, title "VNCmail+", SRC logo.
- LOGIN_SHOW_SUBTITLE=false: the subtitle falls back to the login.title
  i18n string ("Webmail") whenever it differs from APP_NAME - a check
  written for the original Bulwark pairing where they matched. Hiding it
  avoids touching that shared string for every other deployment.
This commit is contained in:
Bernd Rodler
2026-08-05 21:01:38 +02:00
parent e44f2ac97e
commit e1a12b2c23
4 changed files with 76 additions and 14 deletions
+22 -14
View File
@@ -58,20 +58,28 @@ module.exports = {
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",
// Dedicated 1024x1024 app icon: the SRC symbol centred on the SRC dark
// ground (#09090b), generated from public/branding/SRC_Symbol.png into
// build-resources/app-icon.png (NOT build/ - that's electron-builder's own
// gitignored output dir; a source asset living inside it would never get
// committed, which is exactly the bug this comment is warning about one
// paragraph down). 1024 is the size macOS actually wants for the largest
// icns representation ("ICON512@2x"), so nothing gets upsampled.
//
// Deliberately NOT public/icon-512x512.png (what this used to point at):
// that file is the *web* PWA manifest icon, so retouching it for the
// desktop app silently changes the browser/PWA install icon too. Separate
// source, separate concern.
//
// NOTE for whoever runs this next: electron-builder does NOT auto-detect a
// file named `electron-builder.config.js` - its search list is
// electron-builder.{yml,yaml,json,json5,js,cjs,mjs,ts}. Packaging must be
// invoked with an explicit `--config electron-builder.config.js`, or every
// setting in this file is silently ignored and you get stock defaults
// (default Electron atom icon, `dist/` output, productName taken from
// package.json's `name`). See the `dist:*` scripts in package.json, which
// exist so nobody has to remember that.
icon: "build-resources/app-icon.png",
mac: {
target: [
{ target: "dmg", arch: ["x64", "arm64"] },