How Modly Auto-Updater Manages Updates for Packaged Applications Across Operating Systems
Modly's auto-updater uses Electron Updater (electron-updater) from the main process with platform-specific logic that enables automatic patches on Windows and Linux while disabling updates entirely on macOS due to unsigned builds.
Modly, an open-source desktop application built with Electron, implements a sophisticated cross-platform update mechanism that balances automation with user control. The system handles patch updates silently while requiring manual intervention for major and minor releases, with special handling for macOS limitations. All auto-updater logic lives in electron/main/updater.ts and integrates with the UI through src/shared/stores/appStore.ts.
Platform-Specific Update Behavior
Modly's update support varies dramatically by operating system due to code signing requirements.
Windows and Linux: Full Auto-Updater Support
On Windows and Linux, electron-updater operates normally. The updater validates bundle signatures against signed builds, enabling seamless automatic updates. Users receive patch updates without interruption while major and minor releases trigger UI notifications.
macOS: Updates Explicitly Disabled
macOS builds are unsigned—the project lacks an Apple Developer ID. Since electron-updater validates code signatures before applying any update, the updater would fail repeatedly on macOS. The code explicitly disables updates through the updatesSupported constant:
// In electron/main/updater.ts
const updatesSupported = process.platform !== 'darwin';
This platform gate ensures macOS users manually download installers from GitHub Releases rather than experiencing broken auto-update attempts.
Initializing the Auto-Updater
The initAutoUpdater(getWindow) function bootstraps the update system from electron/main/index.ts. It receives a callback returning the current BrowserWindow to enable renderer communication.
Configuration applied when updatesSupported is true:
| Setting | Value | Purpose |
|---|---|---|
autoDownload |
false |
Prevents automatic downloads; app controls when to fetch updates |
autoInstallOnAppQuit |
true |
Silent installation when user quits the application |
disableWebInstaller |
true |
Forces updates from GitHub release assets only |
// From electron/main/index.ts
import { initAutoUpdater } from './updater';
import { createWindow } from './window';
const mainWindow = createWindow();
initAutoUpdater(() => mainWindow);
Update Detection and Scheduling
Modly checks for updates immediately on application startup, then polls every 2 hours using setInterval. The autoUpdater.checkForUpdates() method queries the configured update source (GitHub Releases) for new versions.
Distinguishing Patch vs. Major/Minor Updates
When electron-updater emits the 'update-available' event, Modly implements version parsing logic to categorize the update type:
Patch updates (same major.minor, different patch):
- Automatically downloaded via
autoUpdater.downloadUpdate() - Applied silently on next quit
Major/minor updates (different major or minor version):
- Renderer notified via
updater:major-minor-availableIPC channel - UI prompts user to download new installer from GitHub
This separation prevents disruptive automatic updates that might require manual migration or new dependencies.
// Simplified version comparison logic from updater.ts
const [currentMajor, currentMinor] = currentVersion.split('.').map(Number);
const [newMajor, newMinor] = newVersion.split('.').map(Number);
if (currentMajor === newMajor && currentMinor === newMinor) {
// Patch: auto-download
autoUpdater.downloadUpdate();
} else {
// Major/minor: notify renderer
mainWindow.webContents.send('updater:major-minor-available', { version: newVersion });
}
Applying Downloaded Updates
Once a patch finishes downloading, the 'update-downloaded' event triggers the installation sequence:
- Main process sends
updater:applyingto renderer - Renderer sets
patchUpdateReady = trueinuseAppStore - Short delay allows UI to render "Applying update..." screen
autoUpdater.quitAndInstall(true, true)executes with:- First
true: quit silently - Second
true: run installer after quit
- First
State Management and UI Integration
The shared store in src/shared/stores/appStore.ts exposes update state to the React renderer. Components subscribe to patchUpdateReady to display appropriate UI feedback.
Renderer Event Listener Hook
import { useEffect } from 'react';
import { useAppStore } from '../../shared/stores/appStore';
export function useUpdateListener() {
const setPatchUpdateReady = useAppStore(state => state.setPatchUpdateReady);
const showToast = useAppStore(state => state.showToast);
useEffect(() => {
const onMajorMinor = (_event, { version }) => {
showToast(`New version ${version} available – download from GitHub`);
};
const onApplying = (_event, { version }) => {
setPatchUpdateReady(true);
showToast(`Applying patch ${version}…`);
};
window.electron.ipcRenderer.on('updater:major-minor-available', onMajorMinor);
window.electron.ipcRenderer.on('updater:applying', onApplying);
return () => {
window.electron.ipcRenderer.removeListener('updater:major-minor-available', onMajorMinor);
window.electron.ipcRenderer.removeListener('updater:applying', onApplying);
};
}, [setPatchUpdateReady, showToast]);
}
React UI Component
import { useAppStore } from '../../shared/stores/appStore';
export function PatchUpdateBanner() {
const patchReady = useAppStore(state => state.patchUpdateReady);
if (!patchReady) return null;
return <div className="banner">Applying update… Please wait.</div>;
}
Error Handling and Logging
All updater errors route through Modly's shared logger. The IPC channel in electron/main/ipc-handlers.ts registers the autoUpdater instance for renderer communication, ensuring consistent error propagation across processes.
Summary
- Modly's auto-updater is disabled on macOS (
process.platform !== 'darwin') due to unsigned builds that would fail signature validation - Windows and Linux support automatic patch updates with
autoDownload: falseandautoInstallOnAppQuit: true - Patch updates download and install silently; major/minor releases require manual GitHub download
- Update logic resides in
electron/main/updater.tswith state shared viasrc/shared/stores/appStore.ts - The renderer receives notifications through IPC channels
updater:major-minor-availableandupdater:applying
Frequently Asked Questions
Why doesn't Modly's auto-updater work on macOS?
The macOS builds are unsigned because the project lacks an Apple Developer ID. Since electron-updater validates code signatures before applying updates, it would fail repeatedly on macOS. The updater is explicitly disabled on darwin platforms to prevent broken user experiences, forcing manual downloads from GitHub Releases instead.
How does Modly decide between automatic patches and manual major updates?
The updater parses version strings into major, minor, and patch components when an 'update-available' event fires. If the major and minor numbers match the current installation, it's classified as a patch and downloads automatically. Different major or minor numbers trigger a renderer notification, prompting the user to download a new installer from GitHub.
Can I disable automatic updates in Modly?
Automatic updates require updatesSupported to be true (non-macOS platforms) and depend on autoDownload: false requiring explicit download calls. There is no user-facing toggle to fully disable the update check, though the 2-hour polling interval and manual download gate provide user control over when updates apply.
Where does Modly download updates from?
The disableWebInstaller: true setting forces electron-updater to source updates exclusively from GitHub release assets. Modly does not use web installers or third-party update servers—all binaries must be present in the repository's Releases section with proper version tags.
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 →