How Fluxer Implements Auto-Updater Functionality and Update Channels
Fluxer implements auto-updates using Electron's autoUpdater module combined with the update-electron-app helper, supporting two build channels (stable and canary) that determine update URLs and runtime behavior.
The desktop client in the fluxerapp/fluxer repository provides seamless automatic updates through a carefully architected main-process implementation. This system checks for updates every 12 hours against channel-specific endpoints while exposing manual controls to the renderer process via IPC.
Architecture of the Fluxer Auto-Updater
The auto-updater architecture centers on src/main/Updater.tsx, which orchestrates the update lifecycle and bridges Electron's native capabilities with the React-based UI.
Core Components
The implementation relies on four key components working together:
update-electron-app: Configures the periodic update check (every 12 hours) against Fluxer's static storage endpoint- Electron
autoUpdater: Handles native update lifecycle events includingchecking-for-update,update-available, andupdate-downloaded - IPC Handlers: Exposes
updater-checkandupdater-installchannels to the renderer process for manual control - Event Forwarding: Sends structured
updater-eventmessages to the UI for real-time status display
Update Flow
In src/main/index.tsx, the application calls registerUpdater(getMainWindow) during startup to initialize the system. The configuration in src/main/Updater.tsx sets updateSource.type to StaticStorage and constructs the baseUrl using the active BUILD_CHANNEL, process.platform, and process.arch.
The updater polls https://api.fluxer.app/dl/desktop/<CHANNEL>/<platform>/<arch> every 12 hours. When an update downloads successfully, the main process emits an updater-event with type downloaded, allowing the renderer to prompt users before calling electronApi.updaterInstall() to trigger autoUpdater.quitAndInstall().
Available Update Channels in Fluxer
Fluxer supports two mutually exclusive distribution channels defined in src/common/BuildChannel.tsx, with the active channel baked into the binary at build time.
Stable vs Canary
The repository defines a BuildChannel type accepting only 'stable' or 'canary':
export type BuildChannel = 'stable' | 'canary';
export const BUILD_CHANNEL = 'stable' as BuildChannel;
export const IS_CANARY = BUILD_CHANNEL === 'canary';
export const CHANNEL_DISPLAY_NAME = BUILD_CHANNEL;
Stable serves production-grade releases with standard logging levels, while Canary provides early-access builds with debug-level logging and separate infrastructure ports. The IS_CANARY boolean constant allows conditional logic throughout the codebase to adjust behavior based on the active channel.
Build-Time Channel Configuration
The channel is not runtime-configurable; instead, the build script scripts/set-build-channel.mjs rewrites BuildChannel.tsx during CI/CD:
const channel = process.env.BUILD_CHANNEL || 'stable';
// Rewrites export const BUILD_CHANNEL = '${channel}' as BuildChannel;
Running BUILD_CHANNEL=canary pnpm run build produces a canary binary that queries the canary update endpoint, listens on RPC port 21864 (instead of 21863 for stable), and displays canary-specific branding.
Implementing Auto-Updates in Code
Developers interacting with the Fluxer auto-updater can trigger checks, listen for events, and install updates through the exposed Electron API.
Manual Update Checks
From the renderer process, trigger a manual check by calling electronApi.updaterCheck with a context parameter:
import { useEffect } from 'react';
function useUpdateCheck() {
useEffect(() => {
// Context can be 'user', 'background', or 'focus'
void electronApi.updaterCheck('user');
}, []);
}
This sends an updater-check IPC message to the main process, which stores the context and invokes autoUpdater.checkForUpdates().
Handling Updater Events
Subscribe to updater-event messages to update the UI based on download progress:
useEffect(() => {
const handler = (_event: any, payload: UpdaterEvent) => {
switch (payload.type) {
case 'checking':
setStatus('Checking for updates…');
break;
case 'available':
setStatus(`Update available! Version: ${payload.version ?? 'unknown'}`);
break;
case 'downloaded':
setStatus(`Update downloaded (v${payload.version}). Ready to install.`);
break;
case 'error':
setStatus(`Update error: ${payload.message}`);
break;
}
};
window.ipcRenderer?.on('updater-event', handler);
return () => window.ipcRenderer?.removeListener('updater-event', handler);
}, []);
Installing Updates
Once downloaded, apply the update by invoking the install method, which triggers autoUpdater.quitAndInstall():
async function installUpdate() {
await electronApi.updaterInstall();
}
This call sets an internal quitting flag and restarts the application with the new version.
Summary
- Fluxer uses Electron's
autoUpdaterwith theupdate-electron-apphelper configured insrc/main/Updater.tsxto check for updates every 12 hours - Two build channels exist:
stable(default) andcanary, defined insrc/common/BuildChannel.tsxand set at build time viascripts/set-build-channel.mjs - The update URL follows the pattern
https://api.fluxer.app/dl/desktop/<CHANNEL>/<platform>/<arch> - IPC handlers (
updater-check,updater-install) and events (updater-event) connect the main process updater logic to the React renderer - Channel-specific differences include RPC ports (21863 for stable, 21864 for canary), logging levels, and application branding
Frequently Asked Questions
How do I switch between stable and canary channels in Fluxer?
You cannot switch channels at runtime. The channel is baked into the binary during the build process by setting the BUILD_CHANNEL environment variable before running pnpm run build. The script scripts/set-build-channel.mjs rewrites src/common/BuildChannel.tsx to embed the channel constant, which then determines the update URL, RPC port, and logging behavior for that specific binary.
What is the default update check interval in Fluxer?
By default, Fluxer checks for updates every 12 hours through the update-electron-app configuration in src/main/Updater.tsx. Users can also trigger manual checks immediately by calling electronApi.updaterCheck() from the renderer process, which invokes autoUpdater.checkForUpdates() in the main process.
How does Fluxer handle update errors?
The auto-updater listens for the error event from Electron's autoUpdater module and forwards it to the renderer via the updater-event IPC channel with type error. The UI can display payload.message to inform users of connection issues or download failures without crashing the application.
Where does Fluxer download updates from?
Updates are served from a static storage endpoint constructed as https://api.fluxer.app/dl/desktop/<CHANNEL>/<platform>/<arch>, where <CHANNEL> is either stable or canary based on the BUILD_CHANNEL constant defined at build time in src/common/BuildChannel.tsx.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →