Packaging & Distribution
Turn your Electron app into installers users can download and run. Code signing, notarization, and multi-platform builds—the final steps to production.
Packaging is where many developers get stuck. Code signing is confusing, notarization is slow, and platform differences are frustrating. But it's essential—unsigned apps trigger scary warnings, and users won't trust software that looks suspicious.
What You're Building
Each platform has its own installer format and distribution expectations. Users expect a .dmg on macOS, an .exe installer on Windows, and an AppImage or .deb on Linux.
macOS
- .dmg - Drag to Applications
- .pkg - Guided installer
- .zip - Direct download
Requires code signing + notarization
Windows
- NSIS .exe - Standard installer
- .msi - Enterprise deployment
- Portable - No install needed
Code signing prevents SmartScreen warnings
🐧 Linux
- AppImage - Universal, portable
- .deb - Debian/Ubuntu
- .rpm - Fedora/RHEL
No signing required, but recommended
🎯 VibeBlaster Distribution
VibeBlaster ships as a signed .dmg for macOS and signed NSIS installer for Windows. The whole build process runs in GitHub Actions—push a tag, and installers appear on the Releases page 20 minutes later. No manual steps.
electron-builder Configuration
electron-builder is the standard tool for packaging Electron apps. It handles bundling, code signing, notarization, and creating platform-specific installers—all from a single configuration.
Essential Configuration
Add this to your package.json. The key settings are appId (unique identifier), productName (display name), and publish (for auto-updates).
{
"build": {
"appId": "com.yourcompany.yourapp",
"productName": "Your App Name",
"directories": {
"output": "release",
"buildResources": "build"
},
"files": [
"dist/**/*",
"package.json"
],
"mac": {
"category": "public.app-category.productivity",
"target": ["dmg", "zip"],
"hardenedRuntime": true,
"notarize": { "teamId": "YOUR_TEAM_ID" }
},
"win": {
"target": ["nsis"],
"signingHashAlgorithms": ["sha256"]
},
"linux": {
"target": ["AppImage", "deb"],
"category": "Utility"
},
"publish": {
"provider": "github"
}
}
}Build Commands
npm run build:mac → .dmg + .zip
npm run build:win → .exe installer
npm run build:linux → AppImage + .deb
Output Structure
release/
├── YourApp-1.0.0.dmg
├── YourApp-1.0.0-mac.zip
├── YourApp Setup 1.0.0.exe
└── YourApp-1.0.0.AppImage
Code Signing: Why It Matters
Code signing proves your app comes from you and hasn't been tampered with. Without it, users see scary warnings: "Windows protected your PC" or "App can't be opened because it's from an unidentified developer."
Unsigned App Consequences
- • macOS: "App is damaged and can't be opened" or Gatekeeper blocks it
- • Windows: SmartScreen warning, users must click through scary dialogs
- • Auto-updates: Won't work without code signing
- • User trust: Looks like malware, users won't install
macOS Signing
- 1. Join Apple Developer Program ($99/year)
- 2. Create "Developer ID Application" certificate
- 3. Export as .p12 file from Keychain
- 4. Set CSC_LINK and CSC_KEY_PASSWORD env vars
- 5. electron-builder signs automatically
Also requires notarization (Apple scans your app)
Windows Signing
- 1. Purchase code signing certificate (~$200-500/year)
- 2. Providers: DigiCert, Sectigo, SSL.com
- 3. Export as .pfx file
- 4. Set WIN_CSC_LINK and WIN_CSC_KEY_PASSWORD
- 5. electron-builder signs automatically
EV certificates eliminate SmartScreen warnings immediately
Environment Variables for CI
Store certificates as base64-encoded secrets in your CI system. Never commit certificates to git.
# macOS
CSC_LINK: base64-encoded .p12 certificate
CSC_KEY_PASSWORD: certificate password
APPLE_ID: your-apple-id@email.com
APPLE_APP_SPECIFIC_PASSWORD: app-specific password
APPLE_TEAM_ID: your team ID
# Windows
WIN_CSC_LINK: base64-encoded .pfx certificate
WIN_CSC_KEY_PASSWORD: certificate passwordmacOS Notarization
Starting with macOS 10.15 (Catalina), apps must be notarized by Apple to run without warnings. Notarization uploads your app to Apple's servers for malware scanning. It takes 5-15 minutes.
Notarization Flow
Build & Sign
electron-builder
Upload to Apple
notarytool
Apple Scans
5-15 minutes
Staple Ticket
Ready to ship
💡 electron-builder Handles This
With the right config and environment variables, electron-builder automatically uploads to Apple, waits for approval, and staples the ticket. You just run npm run build:mac and wait. Check the notarization status in Apple's developer portal if something goes wrong.
Automated Builds in CI
The best setup: push a git tag, and CI automatically builds, signs, and publishes installers for all platforms. No manual steps, no "works on my machine" issues.
GitHub Actions Release Workflow
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
jobs:
build:
strategy:
matrix:
include:
- os: macos-latest
build_cmd: build:mac
- os: windows-latest
build_cmd: build:win
- os: ubuntu-latest
build_cmd: build:linux
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run ${{ matrix.build_cmd }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERT }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
# ... other secrets
- uses: softprops/action-gh-release@v1
with:
files: release/*
draft: true✓ CI Benefits
- • Reproducible builds every time
- • Build on actual target OS (not cross-compile)
- • Certificates stay in CI secrets
- • Automatic GitHub Releases
⚠️ Watch Out For
- • macOS notarization adds 10-20 min to builds
- • Windows signing can timeout
- • Large artifacts may need cleanup
- • Test installers before releasing
Packaging Best Practices
Your App Is Ready to Ship
You can now build signed installers for all platforms and distribute them to users. Combined with auto-updates, your release process is fully automated—push a tag and wait for installers.
Next up: Performance. Your app works, it's packaged, it's signed—now let's make sure it's fast and doesn't eat all your users' RAM.