desktop deployment - nself-org/nchat GitHub Wiki
Complete guide for building, signing, and deploying nchat desktop applications for Windows, macOS, and Linux.
- Node.js 20.x or later
- npm or pnpm
- Git
- Windows 10 or later
- Windows SDK 10.0.18362.0 or later (for SignTool)
- NSIS 3.x (automatically installed by electron-builder)
- macOS 10.15 (Catalina) or later
- Xcode Command Line Tools:
xcode-select --install - Apple Developer account (for code signing and notarization)
- Ubuntu 20.04+ or equivalent
- Build tools:
sudo apt-get install rpm fakeroot dpkg - ImageMagick (for icon generation):
sudo apt-get install imagemagick
-
Obtain a Code Signing Certificate
- Purchase from a Certificate Authority (DigiCert, Sectigo, GlobalSign)
- Export as
.pfxfile with password
-
Set Environment Variables
# Local development export WIN_CSC_LINK="/path/to/certificate.pfx" export WIN_CSC_KEY_PASSWORD="your-password" # Or base64 encode for CI base64 -i certificate.pfx -o certificate.b64 export WIN_CSC_LINK="<base64-encoded-content>"
-
GitHub Secrets (for CI/CD)
-
WIN_CSC_LINK: Base64-encoded certificate -
WIN_CSC_KEY_PASSWORD: Certificate password
-
-
Set Up Azure Key Vault
- Create Azure Key Vault
- Upload code signing certificate
- Create service principal
-
Install AzureSignTool
dotnet tool install --global AzureSignTool
-
Set Environment Variables
export AZURE_KEY_VAULT_URI="https://your-vault.vault.azure.net/" export AZURE_CERT_NAME="your-cert-name" export AZURE_CLIENT_ID="your-client-id" export AZURE_CLIENT_SECRET="your-client-secret" export AZURE_TENANT_ID="your-tenant-id"
After code signing, your application may still show SmartScreen warnings until it gains reputation:
- Extended Validation (EV) Certificate: Provides immediate SmartScreen reputation
- Build Reputation: Distribute to users and gather telemetry over time
- Microsoft Defender SmartScreen: Submit your app for analysis
-
Join Apple Developer Program: https://developer.apple.com/programs/
-
Create Certificates in Apple Developer Portal:
- Developer ID Application certificate (for distribution outside Mac App Store)
- Developer ID Installer certificate (for .pkg installers)
-
Download and Install Certificates
- Download from Apple Developer Portal
- Double-click to install in Keychain Access
- Verify with:
security find-identity -v -p codesigning
Method 1: App-Specific Password (Apple ID)
-
Create App-Specific Password
- Go to https://appleid.apple.com/account/manage
- Sign in with your Apple ID
- Generate app-specific password under "Security"
-
Set Environment Variables
export APPLE_ID="[email protected]" export APPLE_ID_PASSWORD="xxxx-xxxx-xxxx-xxxx" # App-specific password export APPLE_TEAM_ID="YOUR_TEAM_ID" # 10-character team ID
Method 2: API Key (Recommended)
-
Create API Key in App Store Connect
- Go to Users and Access > Keys
- Create new API key with "Developer" access
- Download .p8 key file
-
Set Environment Variables
export APPLE_API_KEY="/path/to/AuthKey_XXXXXXXXXX.p8" export APPLE_API_KEY_ID="XXXXXXXXXX" export APPLE_API_ISSUER="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
-
GitHub Secrets
-
APPLE_API_KEY: Base64-encoded .p8 file -
APPLE_API_KEY_ID: Key ID -
APPLE_API_ISSUER: Issuer ID
-
# Export certificate to .p12 file
security export -k ~/Library/Keychains/login.keychain-db \
-t identities \
-f pkcs12 \
-o certificate.p12 \
-P "export-password"
# Base64 encode for GitHub Secrets
base64 -i certificate.p12 -o certificate.b64GitHub Secrets:
-
CSC_LINK: Base64-encoded .p12 certificate -
CSC_KEY_PASSWORD: Export password -
CSC_NAME: Certificate name (e.g., "Developer ID Application: Your Name (TEAM_ID)")
Linux packages typically don't require code signing, but you can sign packages for verification:
# Generate GPG key
gpg --gen-key
# Sign package
dpkg-sig --sign builder nchat_*.deb
# Verify
dpkg-sig --verify nchat_*.deb# Import GPG key
rpm --import your-public-key.asc
# Sign package
rpmsign --addsign nchat-*.rpm
# Verify
rpm --checksig nchat-*.rpm# From project root
pnpm install
pnpm buildThis creates the out/ directory with the static Next.js build.
cd platforms/electron
# Install dependencies
npm install
# Build TypeScript files
npm run build:all
# Package for current platform
npm run pack # Creates unpacked app in dist-electron
# Or build distributables
npm run dist # Current platform
npm run dist:mac # macOS
npm run dist:win # Windows
npm run dist:linux # Linux
npm run dist:all # All platforms (requires appropriate OS)# Build NSIS installer and portable
npm run dist:win
# Outputs:
# - dist-electron/nchat-Setup-1.0.0.exe (installer)
# - dist-electron/nchat-1.0.0-Portable.exe (portable)# Build DMG and PKG for both architectures
npm run dist:mac
# Outputs:
# - dist-electron/nchat-1.0.0-mac-x64.dmg (Intel)
# - dist-electron/nchat-1.0.0-mac-arm64.dmg (Apple Silicon)
# - dist-electron/nchat-1.0.0-mac-x64.pkg (Intel installer)
# - dist-electron/nchat-1.0.0-mac-arm64.pkg (Apple Silicon installer)
# - dist-electron/nchat-1.0.0-mac-x64.zip (Intel archive)
# - dist-electron/nchat-1.0.0-mac-arm64.zip (Apple Silicon archive)# Build all Linux packages
npm run dist:linux
# Outputs:
# - dist-electron/nchat-1.0.0-x86_64.AppImage
# - dist-electron/nchat_1.0.0_amd64.deb
# - dist-electron/nchat-1.0.0.x86_64.rpm
# - dist-electron/nchat-1.0.0-linux-x64.tar.gzIf you need to regenerate icons from a source image:
cd platforms/electron
# From SVG or high-res PNG
node scripts/generate-icons.js /path/to/logo.svg
# This generates:
# - resources/icons/icon.icns (macOS)
# - resources/icons/icon.ico (Windows)
# - resources/icons/[size]x[size].png (all platforms)
# - resources/icons/[size]x[size]/apps/nchat.png (Linux hicolor)The project includes a complete GitHub Actions workflow: .github/workflows/desktop-release.yml
Option 1: Git Tag
# Create and push a version tag
git tag v0.8.0
git push origin v0.8.0Option 2: Manual Workflow Dispatch
- Go to GitHub Actions
- Select "Desktop Release" workflow
- Click "Run workflow"
- Enter version number (e.g., "0.8.0")
- Check "pre-release" if applicable
Configure these in your repository settings (Settings > Secrets and variables > Actions):
Windows Code Signing:
-
WIN_CSC_LINK: Base64-encoded .pfx certificate -
WIN_CSC_KEY_PASSWORD: Certificate password
macOS Code Signing:
-
CSC_LINK: Base64-encoded .p12 certificate -
CSC_KEY_PASSWORD: Certificate password -
CSC_NAME: Certificate name -
KEYCHAIN_PASSWORD: Random password for temporary keychain
macOS Notarization (choose one method):
Method 1: Apple ID
-
APPLE_ID: Apple ID email -
APPLE_ID_PASSWORD: App-specific password -
APPLE_TEAM_ID: Team ID
Method 2: API Key (recommended)
-
APPLE_API_KEY: Base64-encoded .p8 file -
APPLE_API_KEY_ID: Key ID -
APPLE_API_ISSUER: Issuer ID
GitHub Release:
-
GITHUB_TOKEN: Automatically provided by GitHub Actions
- Build Web App: Builds Next.js application (shared artifact)
- Build Windows: Compiles and signs Windows executables
- Build macOS: Compiles, signs, and notarizes macOS bundles
- Build Linux: Creates AppImage, .deb, and .rpm packages
- Create Release: Publishes GitHub release with all artifacts
Upload built packages to:
- GitHub Releases (automated by CI)
- Your own CDN or file server
- S3 bucket
Winget
# Create winget manifest
# Submit PR to: https://github.com/microsoft/winget-pkgsChocolatey
# Create nuspec file
choco pack
choco push nchat.1.0.0.nupkg --source https://push.chocolatey.org/Scoop
{
"version": "1.0.0",
"description": "Team Communication Platform",
"homepage": "https://nself.org",
"license": "MIT",
"url": "https://github.com/nself/nself-chat/releases/download/v1.0.0/nchat-1.0.0-Portable.exe",
"bin": "nchat.exe",
"shortcuts": [["nchat.exe", "nchat"]],
"checkver": "github",
"autoupdate": {
"url": "https://github.com/nself/nself-chat/releases/download/v$version/nchat-$version-Portable.exe"
}
}Homebrew Cask
# Create cask formula
brew create --cask https://github.com/nself/nself-chat/releases/download/v1.0.0/nchat-1.0.0-mac-x64.dmg
# Submit PR to: https://github.com/Homebrew/homebrew-caskSnap Store
snapcraft
snapcraft upload --release=stable nchat_1.0.0_amd64.snapFlathub
# Create flatpak manifest
# Submit to: https://github.com/flathub/flathubAppImage Hub
- Upload to https://www.appimagehub.com/
The app uses electron-updater with GitHub Releases by default. For self-hosted updates:
-
Configure Update Server Edit
electron-builder.yml:publish: - provider: generic url: https://your-update-server.com/releases channel: latest
-
Server Structure
/releases/ /latest.yml (or latest-mac.yml, latest-linux.yml) /nchat-Setup-1.0.0.exe /nchat-1.0.0-mac.zip /nchat-1.0.0.AppImage -
Update Metadata File (
latest.yml)version: 1.0.0 files: - url: nchat-Setup-1.0.0.exe sha512: <file-hash> size: 12345678 path: nchat-Setup-1.0.0.exe sha512: <file-hash> releaseDate: '2026-01-31T12:00:00.000Z'
- Version number updated in
package.json - Release notes prepared
- Code signed and notarized (macOS)
- Tested on clean systems
- Auto-updater tested
- Deep links working (nchat://)
- System tray functional
- Notifications working
- File size under 150MB
- Launch time under 2 seconds
- Memory usage under 100MB idle
Windows:
# Run in Windows Sandbox or VM
# Check SmartScreen behavior
# Verify installer options
# Test auto-launch
# Check protocol handlermacOS:
# Test on both Intel and Apple Silicon
# Verify Gatekeeper doesn't block
# Check notarization: spctl -a -vv /Applications/nchat.app
# Test auto-updaterLinux:
# Test on Ubuntu, Fedora, Arch
# Verify desktop file integration
# Check protocol handler
# Test AppImage on different distros#!/bin/bash
# Quick smoke test for built applications
echo "Testing nchat build..."
# Check file exists
if [ ! -f "dist-electron/nchat"* ]; then
echo "❌ Build not found"
exit 1
fi
# Check file size
SIZE=$(du -sh dist-electron/nchat* | awk '{print $1}')
echo "✓ Build size: $SIZE"
# macOS: Check code signature
if [[ "$OSTYPE" == "darwin"* ]]; then
codesign --verify --deep --strict dist-electron/nchat.app
echo "✓ Code signature valid"
spctl -a -vv dist-electron/nchat.app
echo "✓ Notarization valid"
fi
# Windows: Check signature
if [[ "$OSTYPE" == "msys" ]]; then
signtool verify /pa dist-electron/nchat-Setup-*.exe
echo "✓ Code signature valid"
fi
echo "✅ All tests passed"Error: SignTool not found
# Install Windows SDK
# Or specify SignTool path
set SIGNTOOL_PATH=C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exeSmartScreen Warning
- Expected for new applications without reputation
- Use EV certificate for immediate trust
- Or build reputation over time
NSIS Error
# Clear electron-builder cache
rd /s /q %LOCALAPPDATA%\electron-builder\Cache
npm run dist:winNotarization Failed: Invalid Developer ID
# Verify certificate name
security find-identity -v -p codesigning
# Ensure CSC_NAME matches exactly
export CSC_NAME="Developer ID Application: Your Name (TEAM_ID)"Notarization Timeout
- Notarization can take 10-60 minutes
- Check status:
xcrun notarytool history --apple-id YOUR_APPLE_ID - View logs:
xcrun notarytool log <submission-id> --apple-id YOUR_APPLE_ID
Gatekeeper Blocks App
# Remove quarantine attribute (for testing only)
xattr -cr /Applications/nchat.app
# For distribution, ensure proper notarizationAppImage Won't Run
# Make executable
chmod +x nchat-*.AppImage
# Install FUSE if needed (older systems)
sudo apt-get install fuse libfuse2
# Or extract and run
./nchat-*.AppImage --appimage-extract
./squashfs-root/nchat.deb Install Fails
# Check dependencies
dpkg -I nchat_*.deb
# Install missing dependencies
sudo apt-get install -fProtocol Handler Not Working
# Re-register handler
xdg-mime default nchat.desktop x-scheme-handler/nchat
# Test
xdg-open nchat://testSlow Builds
- Use
--dirflag for faster development builds - Enable local caching
- Use faster compression for dev builds
Large Package Size
- Review included node_modules
- Use
asarcompression - Exclude unnecessary files in
electron-builder.yml
- Documentation: https://docs.nself.org
- Issues: https://github.com/nself/nself-chat/issues
- Community: https://community.nself.org
Last Updated: January 31, 2026 Version: 0.8.0