# How Fluxer Implements Auto-Updater Functionality and Update Channels

> Discover how Fluxer implements auto-updater functionality using Electron and update-electron-app. Explore stable and canary update channels for seamless application updates.

- Repository: [Fluxer/fluxer](https://github.com/fluxerapp/fluxer)
- Tags: how-to-guide
- Published: 2026-03-17

---

**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`](https://github.com/fluxerapp/fluxer/blob/main/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 including `checking-for-update`, `update-available`, and `update-downloaded`
- **IPC Handlers**: Exposes `updater-check` and `updater-install` channels to the renderer process for manual control
- **Event Forwarding**: Sends structured `updater-event` messages to the UI for real-time status display

### Update Flow

In [`src/main/index.tsx`](https://github.com/fluxerapp/fluxer/blob/main/src/main/index.tsx), the application calls `registerUpdater(getMainWindow)` during startup to initialize the system. The configuration in [`src/main/Updater.tsx`](https://github.com/fluxerapp/fluxer/blob/main/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`](https://github.com/fluxerapp/fluxer/blob/main/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'`:

```typescript
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`](https://github.com/fluxerapp/fluxer/blob/main/BuildChannel.tsx) during CI/CD:

```typescript
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:

```typescript
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:

```typescript
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()`:

```typescript
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 `autoUpdater`** with the **`update-electron-app`** helper configured in [`src/main/Updater.tsx`](https://github.com/fluxerapp/fluxer/blob/main/src/main/Updater.tsx) to check for updates every 12 hours
- Two **build channels** exist: `stable` (default) and `canary`, defined in [`src/common/BuildChannel.tsx`](https://github.com/fluxerapp/fluxer/blob/main/src/common/BuildChannel.tsx) and set at build time via `scripts/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`](https://github.com/fluxerapp/fluxer/blob/main/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`](https://github.com/fluxerapp/fluxer/blob/main/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`](https://github.com/fluxerapp/fluxer/blob/main/src/common/BuildChannel.tsx).