π₯οΈ Electron Desktop App
This guide covers building and running the Libre WebUI frontend as an Electron desktop application for macOS, Windows, and Linux.
π― Overviewβ
The Electron desktop app provides:
- Desktop window integration - Native window management and application menus
- Offline-first design - Works with local Ollama without internet
- Platform packages - DMG/ZIP, Windows Setup/portable EXE, AppImage, and DEB targets
- Backend detection - Connects to an existing backend and logs manual start instructions when it is absent
π Prerequisitesβ
Before building the desktop app, ensure you have:
- Node.js 22.22+ installed
- npm or yarn package manager
- The build tools required by the target operating system. On macOS, install
Xcode Command Line Tools:
xcode-select --install
- A separately running Libre WebUI backend connected to Ollama or configured model-provider plugins
To use Work, also install and start Docker on the machine running the backend. Docker is not bundled in the desktop application.
π Quick Startβ
Development Modeβ
Run the app in development mode with hot reloading:
# Start both frontend and Electron together
npm run electron:dev
This will:
- Start the Vite development server on port 5173
- Wait for the frontend to be ready
- Launch Electron pointing to the dev server
Production Buildsβ
Build on the operating system matching the desired package:
# macOS arm64: DMG and ZIP
npm run electron:build
# Windows: Setup and portable EXE
npm run electron:build:win
# Linux: AppImage and DEB
npm run electron:build:linux
Packages are written to dist-electron/. The configured release names are:
- macOS:
Libre-WebUI-Frontend-{version}-mac-arm64.dmgand.zip - Windows:
Libre-WebUI-Frontend-Setup-{version}.exeandLibre-WebUI-Frontend-{version}.exe - Linux:
Libre-WebUI-Frontend-{version}.AppImageandLibre-WebUI-Frontend-{version}-{arch}.deb
ποΈ Architectureβ
How It Worksβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Electron App β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β Main Process β β Renderer Process β β
β β (Node.js) β β (React Frontend) β β
β β β β β β
β β β’ Window mgmt β β β’ UI rendering β β
β β β’ Menu bar β β β’ API calls to backend β β
β β β’ Backend checkβ β β’ WebSocket connection β β
β βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Communicates with β
β External Backend (port 3001) β
β β β
β Ollama or configured model provider β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Work in the Desktop Appβ
The Electron package is a frontend client. It does not bundle the Libre WebUI backend, Docker, or a Work container runtime. Work availability is determined by the separately running backend:
- a native backend that can run
docker infocan create task-scoped Work containers and named volumes; - a backend running in the standard Libre WebUI Docker image reports Work as unavailable; and
- the Electron app continues to support Chat when Work is unavailable.
Work files live on the backend's Docker host, not inside the Electron app. The embedded preview uses a dynamically assigned loopback port on that backend host, so preview works only when the desktop client and backend are on the same machine. A custom Electron build pointed at a remote backend can still use Work conversation and file APIs, but it cannot reach that server's loopback preview URL.
Key Filesβ
| File | Description |
|---|---|
electron/main.js | Main Electron process |
electron/preload.js | Preload script for security |
electron/splash.html | Splash screen during startup |
electron-builder.yml | Build configuration |
βοΈ Configurationβ
electron-builder.ymlβ
The build configuration supports:
appId: com.librewebui.app
productName: Libre WebUI Frontend
mac:
category: public.app-category.productivity
target:
- target: dmg
arch:
- arm64 # Apple Silicon
- target: zip
arch:
- arm64
darkModeSupport: true
hardenedRuntime: true
Available Scriptsβ
| Script | Description |
|---|---|
npm run electron:dev | Development mode with hot reload |
npm run electron:build | Build macOS arm64 DMG and ZIP |
npm run electron:build:win | Build Windows Setup and portable EXE |
npm run electron:build:linux | Build Linux AppImage and DEB |
npm run electron:verify:mac | Verify the packaged macOS application |
npm run electron:pack | Build unpacked output without an installer |
π¨ macOS Integrationβ
Title Barβ
The app uses a custom title bar style (hiddenInset) for a native macOS look:
- Traffic light buttons integrated into the sidebar
- Extra padding added to avoid overlap with controls
- Draggable title bar area for window movement
Window Featuresβ
- Minimum size: 800x600 pixels
- Default size: 1400x900 pixels
- Dark mode support: Follows system preference
- Traffic light position: Custom positioned at (12, 12)
Menu Barβ
Full native menu bar with:
- App menu (About, Preferences, Quit)
- Edit menu (Undo, Redo, Cut, Copy, Paste)
- View menu (Reload, DevTools, Zoom)
- Window menu (Minimize, Zoom, Full Screen)
- Help menu (Documentation, GitHub, Report Issue)
π§ Troubleshootingβ
Common Issuesβ
1. App shows "Connecting to backend..." forever
The backend needs to be running separately. Start it with:
npm run dev:backend
Or run the full development environment:
npm run dev
2. Click events not working in sidebar
This was fixed by adding -webkit-app-region: no-drag to interactive elements. If you experience this, ensure you have the latest version.
3. Logo/icons not displaying
Assets need relative paths for file:// protocol. Use ./logo.png instead of /logo.png.
4. Navigation doesn't work after clicking
The app uses HashRouter instead of BrowserRouter for file:// protocol compatibility. This is handled automatically.
Build Errorsβ
SQLite/SQLCipher compilation errors:
# Clear npm cache and rebuild
rm -rf node_modules
npm install
npm run electron:build
macOS blocks the downloaded application as damaged:
Libre WebUI temporarily uses an ad-hoc signature for macOS builds. This keeps the application bundle structurally valid, but it does not identify the publisher to Apple and cannot be notarized. After copying the application to Applications, approve it in System Settings β Privacy & Security β Open Anyway.
If macOS does not offer that option, remove the quarantine attribute only after verifying that the application came from the official Libre WebUI release:
xattr -dr com.apple.quarantine "/Applications/Libre WebUI Frontend.app"
open "/Applications/Libre WebUI Frontend.app"
Do not disable Gatekeeper globally. Seamless distribution still requires a Developer ID Application certificate and Apple notarization.
π¦ Distributionβ
Creating a Signed Buildβ
For App Store or notarized distribution:
-
Get an Apple Developer account
-
Create signing certificates in Xcode
-
Create entitlements file at
electron/entitlements.mac.plist -
Remove the temporary
identity: '-'override and configure signing inelectron-builder.yml:mac:hardenedRuntime: truegatekeeperAssess: falseentitlements: electron/entitlements.mac.plistentitlementsInherit: electron/entitlements.mac.plistnotarize: true -
Provide CI credentials through
CSC_LINK,CSC_KEY_PASSWORD, and one of electron-builder's supported Apple notarization credential sets.
GitHub Releasesβ
The build configuration includes GitHub release support:
publish:
provider: github
owner: libre-webui
repo: libre-webui
To publish a release:
# Build and publish
npm run electron:build -- --publish always
π Securityβ
Context Isolationβ
The app uses proper security practices:
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
webSecurity: true,
preload: path.join(__dirname, 'preload.js'),
}
External Linksβ
External links are opened in the default browser, not inside the app:
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
try {
const target = new URL(url);
if (target.protocol === 'http:' || target.protocol === 'https:') {
shell.openExternal(target.toString());
}
} catch {
// Refuse malformed and non-web schemes.
}
return { action: 'deny' };
});
π§ Limitationsβ
Current Limitationsβ
- macOS architecture - Current macOS packages support Apple Silicon
(
arm64) only; Windows and Linux have their own configured build targets - Requires external backend - The backend must run separately
- Work depends on backend Docker - The desktop package does not include a container runtime
- No auto-updates - Updates require downloading and installing a new package
Future Plansβ
- Bundled backend option
- Auto-update functionality
- Universal macOS binary (arm64 + x64)
π Technical Detailsβ
Bundle Contentsβ
The built app includes:
- Electron framework (~200MB)
- Built frontend (~2MB)
- Plugin configurations (~50KB)
- Assets and icons
Performanceβ
- Startup time: ~2-3 seconds
- Memory usage: ~150-300MB (depends on chat history)
- Disk space: ~250MB installed
π Ready to build? Run the platform command above and find the package in
dist-electron/.
See Work: Isolated Workspaces for runtime, provider, storage, and preview security details.