How Fluxer Manages User Data Paths and Desktop Configuration Persistence
Fluxer isolates per-user data into channel-specific Electron userData directories and persists desktop settings via JSON files stored in that location.
Fluxer is an Electron-based desktop application that separates user data by release channel to prevent configuration conflicts between stable and canary builds. The application determines where to store settings at runtime using a dedicated path resolution system. Understanding how Fluxer manages user data paths and desktop configuration persistence is essential for debugging installation issues or extending the app's configuration capabilities.
Channel-Specific User Data Directories
Fluxer stores all per-user data in a dedicated Electron userData directory chosen at runtime based on the build channel. During startup, the main process calls configureUserDataPath() located in fluxer_desktop/src/common/UserDataPath.tsx to establish the storage location.
The function executes a five-step resolution process:
- Reads the compile-time
BUILD_CHANNELconstant. - Maps the channel to a folder name via
channelStorageDirectoryMap(fluxerfor stable,fluxercanaryfor canary). - Builds an absolute path under the OS-provided app-data directory using
app.getPath('appData'). - Sets the Electron userData path via
app.setPath('userData', base)so all subsequent API calls point to that folder. - Returns the resolved
channel,directoryName, andbasepath for logging and downstream use.
// fluxer_desktop/src/common/UserDataPath.tsx
export function configureUserDataPath(): UserDataPaths {
const channel = BUILD_CHANNEL;
const {directoryName, base} = resolveUserDataPaths(channel);
app.setPath('userData', base); // ← centralise all user-data here
return {channel, directoryName, base};
}
Because the userData folder is tied to the channel, stable and canary installations maintain completely separate sets of settings, caches, and window-state files, preventing cross-contamination.
Persisting Desktop Configuration to JSON
All desktop-wide settings are persisted inside the resolved userData directory as individual JSON files.
Application Settings Storage
The custom app URL and other preferences live in settings.json. The fluxer_desktop/src/common/DesktopConfig.tsx module handles persistence through two primary functions:
loadDesktopConfig(userDataPath): Reads the JSON file on application launch.setCustomAppUrl(url): Writes configuration changes back to disk viasaveDesktopConfig().
// fluxer_desktop/src/common/DesktopConfig.tsx
export function loadDesktopConfig(userDataPath: string): void {
configPath = path.join(userDataPath, CONFIG_FILE_NAME);
if (fs.existsSync(configPath)) {
const data = fs.readFileSync(configPath, 'utf-8');
config = JSON.parse(data);
}
}
export function setCustomAppUrl(appUrl: string | null): void {
if (appUrl) config.app_url = appUrl; else delete config.app_url;
saveDesktopConfig(); // writes back to settings.json
}
Window State Management
Window size and position persist to window-state.json. The fluxer_desktop/src/main/Window.tsx module computes the file path using getWindowStateFile(), which concatenates app.getPath('userData') with the filename. On window close or resize, the application writes the WindowBounds object; on startup, it restores the bounds only if they remain valid for the current display configuration.
// fluxer_desktop/src/main/Window.tsx (excerpt)
function getWindowStateFile(): string {
if (!windowStateFile) {
const userDataPath = app.getPath('userData');
windowStateFile = path.join(userDataPath, 'window-state.json');
}
return windowStateFile;
}
Startup Initialization Sequence
The entry point in fluxer_desktop/src/main/index.tsx orchestrates the initialization order to ensure the environment is configured before loading persisted state:
// fluxer_desktop/src/main/index.tsx (excerpt)
const userDataConfig = configureUserDataPath(); // ← pick folder
log.info('Configured user data storage', userDataConfig);
loadDesktopConfig(userDataConfig.base); // ← load settings.json
This sequence guarantees that app.getPath('userData') returns the correct channel-specific directory before any configuration files are accessed.
Working with User Data Paths in Practice
To read or write custom configuration files alongside Fluxer's built-in settings, reference the resolved userData path:
// Example: manually persisting a new setting
import fs from 'node:fs';
import path from 'node:path';
import {app} from 'electron';
function saveMyFlag(value: boolean) {
const file = path.join(app.getPath('userData'), 'my-flag.json');
fs.writeFileSync(file, JSON.stringify({enabled: value}), 'utf-8');
}
To override the application URL for local development:
import {configureUserDataPath} from '@electron/common/UserDataPath';
import {setCustomAppUrl, getAppUrl} from '@electron/common/DesktopConfig';
const paths = configureUserDataPath(); // sets app.getPath('userData')
setCustomAppUrl('http://localhost:5173');
console.log('Running URL →', getAppUrl());
Summary
- Channel isolation: Fluxer uses
configureUserDataPath()to create separate directories for stable (fluxer) and canary (fluxercanary) builds, preventing settings leakage between channels. - Centralized resolution: The
userDatapath is set once at startup viaapp.setPath(), ensuring all Electron APIs and custom code reference the same base directory. - JSON persistence: Desktop configuration (
settings.json) and window state (window-state.json) are stored as plain JSON files within the userData directory. - Deterministic initialization: The main process resolves the data path before loading any configuration, guaranteeing consistent file access throughout the application lifecycle.
Frequently Asked Questions
Where does Fluxer store user data on disk?
Fluxer stores user data in a channel-specific subdirectory under the operating system's standard application data folder. On Windows, this is typically %APPDATA%/fluxer or %APPDATA%/fluxercanary; on macOS, ~/Library/Application Support/fluxer or ~/Library/Application Support/fluxercanary. The exact path is determined at runtime by configureUserDataPath() in fluxer_desktop/src/common/UserDataPath.tsx.
How do stable and canary builds keep settings separate?
The build channel (defined by the BUILD_CHANNEL constant at compile time) maps to a specific directory name via channelStorageDirectoryMap. Stable builds use the fluxer folder, while canary builds use fluxercanary. Because Electron's userData path is set to this channel-specific folder during startup, each channel maintains independent settings.json and window-state.json files.
Can I manually edit Fluxer configuration files?
Yes. Because Fluxer persists configuration as plain JSON files (settings.json and window-state.json) in the userData directory, you can manually edit these files when the application is not running. Changes take effect on the next launch, though invalid JSON or malformed window bounds may cause the application to fall back to default values.
What happens to window position if the display configuration changes?
When restoring window bounds from window-state.json, Fluxer validates that the saved coordinates are still within the bounds of the current display configuration. If the display has been disconnected or the resolution changed such that the window would appear off-screen, the application discards the persisted state and uses default dimensions instead.
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 →