This document describes the build, packaging, and distribution system for LobeChat's Electron-based desktop application. It covers the multi-platform build pipeline, code signing, release channels, and automated distribution through GitHub Releases.
Scope: This page focuses on the desktop application packaging and distribution. For information about the desktop application architecture and IPC communication, see Electron Desktop Integration. For deployment strategies in general, see Deployment Options.
The desktop application build process transforms the Next.js web application into native executables for macOS, Windows, and Linux using Electron and electron-builder.
Build Pipeline Flow
The desktop build executes these stages in sequence:
Sources: package.json40-54 .github/workflows/release-desktop-beta.yml1-252
The desktop build is orchestrated through npm scripts defined in the root package.json:
| Script | Purpose | Components |
|---|---|---|
desktop:build | Complete build pipeline | Runs all stages sequentially |
desktop:build-next | Next.js compilation | Calls build:electron |
desktop:prepare-dist | Distribution preparation | Executes moveNextExports.ts |
desktop:build-electron | Electron packaging | Executes buildElectron.ts |
build:electron | Next.js build with desktop flag | Sets NEXT_PUBLIC_IS_DESKTOP_APP=1 |
Desktop-Specific Next.js Build
This build sets the NEXT_PUBLIC_IS_DESKTOP_APP flag which triggers desktop-specific code paths in the application, such as using local PGlite database instead of server PostgreSQL.
Sources: package.json40-54
The GitHub Actions workflow uses a matrix strategy to build for multiple platforms in parallel:
This creates four parallel build jobs:
| Runner | Platform | Architecture | Output Formats |
|---|---|---|---|
macos-latest | macOS | ARM64 (Apple Silicon) | .dmg, .zip, latest-mac.yml |
macos-15-intel | macOS | x64 (Intel) | .dmg, .zip, latest-mac.yml |
windows-2025 | Windows | x64 | .exe, latest.yml |
ubuntu-latest | Linux | x64 | .AppImage, .deb, .rpm, .snap, .tar.gz |
macOS builds require code signing and notarization for distribution:
The certificate is stored as a base64-encoded string in GitHub secrets and decoded during the build process. Notarization occurs automatically after signing.
Windows builds do not require code signing in the workflow, but use the default electron-builder configuration:
The temporary directory is explicitly set to avoid path length issues on Windows.
Sources: .github/workflows/release-desktop-beta.yml86-144
LobeChat desktop uses two distribution channels controlled by version naming:
Channel Detection Logic
The workflow determines the channel by checking the release tag:
The build process sets the UPDATE_CHANNEL environment variable:
| Channel | UPDATE_CHANNEL | Auto-Update Behavior |
|---|---|---|
| Beta | beta | Receives beta updates |
| Stable | Not set | Receives stable updates only |
This channel information is embedded in the built application and used by the auto-update system to fetch appropriate updates.
Sources: .github/workflows/release-desktop-beta.yml29-50 .github/workflows/release-desktop-beta.yml106-143
The workflow uses job dependencies to ensure correct execution order:
This dependency chain ensures that:
Sources: .github/workflows/release-desktop-beta.yml52-159 .github/workflows/release-desktop-beta.yml151-252
Electron's auto-updater requires a single latest-mac.yml file that describes available updates. However, building for both Intel and Apple Silicon creates two separate YAML files with the same name. The solution is to merge them into a unified manifest.
Merging Strategy
The mergeMacReleaseFiles.js script combines the two architecture-specific YAML files:
Merge Implementation
The merge process:
latest-mac.yml filesfiles arrays from bothThe merged file allows the auto-updater to select the appropriate binary based on the user's system architecture.
Sources: .github/workflows/release-desktop-beta.yml161-215
Each platform build produces specific artifacts:
| Platform | Primary Installer | Update Manifest | Checksum Files |
|---|---|---|---|
| macOS ARM | *.dmg, *.zip | latest-mac.yml | *.dmg.blockmap |
| macOS Intel | *.dmg, *.zip | latest-mac.yml | *.dmg.blockmap |
| Windows | *.exe | latest.yml | *.exe.blockmap |
| Linux | *.AppImage, *.deb, *.rpm, *.snap, *.tar.gz | latest-linux.yml | *.AppImage.blockmap |
The final publish step uploads all artifacts:
This glob pattern captures:
latest-*.yml update manifestsThe artifacts are attached to the GitHub Release that triggered the workflow, making them publicly downloadable.
Sources: .github/workflows/release-desktop-beta.yml236-251
The workflow:set-desktop-version script updates version numbers before building:
This script (likely scripts/electronWorkflow/setDesktopVersion.ts) updates:
package.json version fieldThe version flows from the Git tag through the build process into both the application binary and the installer filename, ensuring consistency across the distribution.
Sources: .github/workflows/release-desktop-beta.yml98-99 package.json108
The desktop build requires specific environment variables:
| Variable | Purpose | Example Value |
|---|---|---|
UPDATE_CHANNEL | Auto-update channel | beta or empty |
APP_URL | Local dev server URL | http://localhost:3015 |
DATABASE_URL | PostgreSQL connection (not used in desktop) | postgresql://postgres@localhost:5432/postgres |
KEY_VAULTS_SECRET | Encryption key for sensitive data | Base64-encoded secret |
NEXT_PUBLIC_DESKTOP_PROJECT_ID | Analytics project ID | Umami project ID |
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL | Analytics endpoint | Umami base URL |
macOS builds additionally require:
| Variable | Purpose |
|---|---|
CSC_LINK | Base64-encoded .p12 certificate |
CSC_KEY_PASSWORD | Certificate password |
APPLE_ID | Apple Developer ID for notarization |
APPLE_APP_SPECIFIC_PASSWORD | App-specific password |
APPLE_TEAM_ID | Apple Team ID |
These credentials enable the build to:
Sources: .github/workflows/release-desktop-beta.yml106-117
Before building, the workflow runs code quality checks:
This ensures that:
The gate job acts as a synchronization point:
This job only succeeds if all builds complete successfully, preventing partial releases.
Sources: .github/workflows/release-desktop-beta.yml52-159
Each platform generates an update manifest file:
latest-mac.yml - Contains both Intel and ARM buildslatest.yml - Contains Windows x64 buildlatest-linux.yml - Contains AppImage buildManifest Structure
These YAML files contain:
The Electron auto-updater reads these manifests to determine if updates are available and downloads the appropriate installer.
The UPDATE_CHANNEL environment variable set during build determines which releases the app checks:
Beta builds (UPDATE_CHANNEL=beta):
- Check GitHub releases tagged with beta/alpha/rc/nightly/next
Stable builds (UPDATE_CHANNEL unset):
- Check GitHub releases with pure semantic versions
This allows beta testers to receive cutting-edge updates while stable users only get production releases.
Sources: .github/workflows/release-desktop-beta.yml106 .github/workflows/release-desktop-beta.yml224-251
Desktop releases are documented in the main CHANGELOG.md:
The changelog service can fetch and display these updates in-app:
The changelog index tracks version ranges and images for each major update, allowing the desktop app to display relevant release notes.
Sources: CHANGELOG.md1-70 src/server/services/changelog/index.ts1-221 docs/changelog/index.json1-181
The matrix strategy enables parallel builds across GitHub Actions runners:
Total build time with parallelization: ~15-25 minutes
- macOS ARM: ~15 minutes
- macOS Intel: ~15 minutes
- Windows: ~20 minutes
- Linux: ~10 minutes
Sequential build time would be: ~60 minutes
Efficiency gain: ~60-75%
The workflow does not explicitly use action caching, but relies on:
Desktop builds require increased Node.js memory:
This allocates 8GB of heap space to prevent out-of-memory errors during the Next.js build phase, particularly when processing large bundles and optimizing assets.
Sources: package.json40 .github/workflows/release-desktop-beta.yml84-88
Generated installers follow consistent naming patterns:
| Platform | Pattern | Example |
|---|---|---|
| macOS DMG | LobeChat-{version}-{arch}.dmg | LobeChat-2.0.0-beta.1-arm64.dmg |
| macOS ZIP | LobeChat-{version}-{arch}-mac.zip | LobeChat-2.0.0-beta.1-x64-mac.zip |
| Windows | LobeChat-Setup-{version}.exe | LobeChat-Setup-2.0.0-beta.1.exe |
| Linux AppImage | LobeChat-{version}.AppImage | LobeChat-2.0.0-beta.1.AppImage |
| Linux DEB | lobe-chat_{version}_amd64.deb | lobe-chat_2.0.0-beta.1_amd64.deb |
macOS files include architecture suffixes:
arm64 - Apple Silicon (M1/M2/M3)x64 - Intel processorsThis allows users to manually select the correct build when downloading, though the auto-updater handles this automatically.
Sources: .github/scripts/pr-comment.js40-52
Build artifacts are stored temporarily during the workflow:
Artifacts are kept for 1 day to allow debugging of failed builds, then automatically deleted to save storage.
Beta builds include analytics tracking:
This enables tracking of:
Separate project IDs for beta and stable builds allow independent tracking of each channel.
Sources: .github/workflows/release-desktop-beta.yml116-117 .github/workflows/release-desktop-beta.yml145-149
Refresh this wiki