# How to Configure Persistent Settings Using electron-store in draw.io Desktop

> Learn how to configure persistent settings in draw.io Desktop with electron-store. This guide shows you how to manage user preferences for a seamless experience.

- Repository: [draw.io/drawio-desktop](https://github.com/jgraph/drawio-desktop)
- Tags: how-to-guide
- Published: 2026-03-05

---

**draw.io Desktop persists user preferences—including window geometry, spell-check toggles, and update flags—using electron-store, which automatically manages a JSON configuration file in the application's user data directory.**

The jgraph/drawio-desktop repository implements a robust configuration layer built on **electron-store** to maintain state across application sessions. According to the source code in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js), the implementation wraps the store API with defensive programming patterns to ensure the diagramming application remains stable even when file system permissions prevent configuration access.

## Initializing electron-store in the Main Process

The store is instantiated once during application startup inside the main process. The initialization uses a try-catch block to prevent startup failures if the configuration directory is inaccessible.

In [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) at line 14, the store is created as follows:

```javascript
import Store from 'electron-store';
// ...
let store;
try {
    store = new Store();
} catch (e) {
    console.error('Failed to initialize electron-store:', e);
    store = null;
}

```

This pattern ensures that the `store` variable is either a functional electron-store instance or `null`, allowing subsequent code to fail gracefully rather than crashing the application.

## Reading Persistent Settings with Default Fallbacks

Throughout the codebase, settings are retrieved using a null-safe pattern that supplies sensible defaults when keys are missing or the store is unavailable. The standard idiom checks `store != null` before calling `store.get('key')`.

**Spell-check configuration** (lines 82-84) demonstrates reading a boolean with platform-specific defaults:

```javascript
let enableSpellCheck = store != null ? store.get('enableSpellCheck') : false;
enableSpellCheck = enableSpellCheck != null ? enableSpellCheck : isMac;

```

**Window geometry restoration** (line 161) uses string parsing with comma-separated fallback values:

```javascript
let lastWinSizeStr = (store && store.get('lastWinSize')) || '1200,800,0,0,false,false';

```

Other flags like `enableStoreBkp` and `isGoogleFontsEnabled` follow this same defensive retrieval pattern, ensuring the application launches with functional defaults even on first run or when the store is uninitialized.

## Persisting Changes with store.set()

When users modify preferences or when the application state changes, values are written using `store.set(key, value)`. This synchronous API immediately updates the JSON file in the user's application data directory (`~/Library/Application Support/draw.io` on macOS or `%APPDATA%\draw.io` on Windows).

**Window size preservation** (lines 251-257) serializes geometry state into a comma-delimited string:

```javascript
store.set('lastWinSize',
    size[0] + ',' + size[1] + ',' + pos[0] + ',' + pos[1] + ',' +
    win.isMaximized() + ',' + win.isFullScreen());

```

**User preference toggles** are persisted at specific interaction points:
- Line 992: `store.set('enableSpellCheck', enableSpellCheck);`
- Line 1005: `store.set('enableStoreBkp', enableStoreBkp);`
- Line 1018: `store.set('isGoogleFontsEnabled', isGoogleFontsEnabled);`

**Auto-update control** uses the `dontCheckUpdates` key, written when users disable update prompts (line 1433) and cleared when re-enabled (line 1049):

```javascript
store.set('dontCheckUpdates', true);   // Disabling updates
store.set('dontCheckUpdates', false);  // Re-enabling updates

```

## Accessing Settings from the Renderer Process

While electron-store operates in the main process, draw.io Desktop exposes configuration APIs to the renderer via IPC bridges defined in [`src/main/electron-preload.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron-preload.js). This allows the frontend to trigger persistent changes without direct store access.

**Main process handler** (in [`electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/electron.js)):

```javascript
ipcMain.on('set-preference', (e, { key, value }) => {
    if (store) store.set(key, value);
});

```

**Preload script exposure** ([`electron-preload.js`](https://github.com/jgraph/drawio-desktop/blob/main/electron-preload.js)):

```javascript
const { ipcRenderer, contextBridge } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
    setPreference: (key, value) => ipcRenderer.send('set-preference', { key, value })
});

```

**Renderer usage**:

```javascript
window.electronAPI.setPreference('enableSpellCheck', true);

```

This architecture maintains security boundaries while allowing the React-based frontend to persist user choices.

## Summary

- **Initialization**: Create the store in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) with try-catch error handling to set `store` to either an instance or `null`.
- **Defensive Reading**: Always check `store != null` before calling `store.get()`, providing explicit default values for missing keys.
- **Synchronous Writing**: Use `store.set(key, value)` to immediately persist changes to the JSON configuration file in the user's application data directory.
- **Cross-Process Access**: Expose configuration methods to the renderer via `contextBridge` and `ipcMain` rather than accessing electron-store directly from the frontend.
- **Storage Location**: Configuration is automatically managed in platform-specific paths—macOS uses `~/Library/Application Support/draw.io` while Windows uses `%APPDATA%\draw.io`.

## Frequently Asked Questions

### Where does draw.io Desktop store the electron-store configuration file?

electron-store automatically writes to the application's user data directory. On macOS, this is `~/Library/Application Support/draw.io/config.json`, while on Windows it resides in `%APPDATA%\draw.io\config.json`. The library handles path resolution and file creation automatically without requiring explicit filesystem code.

### What happens if electron-store fails to initialize?

If initialization fails due to permissions or corruption, the catch block in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) sets `store = null`. The application continues running using hardcoded defaults for all settings. Every subsequent read and write operation checks `store != null` before accessing the API, ensuring the diagram editor remains functional even when persistence is unavailable.

### How do I add a new persistent setting to draw.io Desktop?

First, define a default value using the null-safe retrieval pattern: `const mySetting = store != null ? store.get('myKey') : defaultValue;`. Then persist changes using `store.set('myKey', newValue)` when the user modifies the setting. If the setting must be controlled from the renderer, add an IPC handler in the main process and expose the method through the preload script as shown in the cross-process access pattern.

### Can I access electron-store directly from the renderer process?

No, direct access is blocked by Electron's context isolation for security reasons. draw.io Desktop uses the preload script ([`src/main/electron-preload.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron-preload.js)) to expose specific, controlled methods via `contextBridge`. The renderer calls these exposed methods, which use `ipcRenderer` to send messages to the main process where electron-store actually executes the read or write operations.