Usage
This page covers how window.Electron is built and consumed, the error-handling pattern every call follows, the React hooks, and how to extend the bridge with your own IPC channels. For the full grouped method list, jump to Reference: API surface at the bottom.
The window.Electron bridge
electron/preload.ts (scaffolded by dae init) builds the bridge and exposes it:
import { contextBridge, ipcRenderer } from 'electron';
import { createElectronBridge } from '@devioarts/electron/preload';
contextBridge.exposeInMainWorld('Electron', createElectronBridge());
From renderer code, every method is a typed, promise-based call over IPC:
window.Electron.minimize();
const version = await window.Electron.getAppVersion();
const platform = await window.Electron.getPlatform(); // 'darwin' | 'win32' | 'linux' | ...
Methods take positional arguments (clipboard.writeText(text)), not a single options object — this is deliberate, and plugins follow the same convention (see Plugins).
IpcResult<T> — error handling without try/catch
Many handlers (registered via trustedIpcHandleSafe, see Architecture) return IpcResult<T> — { ok: true, data } on success, or { ok: false, error: { code, message } } on failure — instead of throwing. code is one of VALIDATION, NOT_CONFIGURED, RUNTIME, UNSUPPORTED_OS, FORBIDDEN, UNKNOWN. Callers check result.ok rather than wrapping calls in try/catch:
const result = await window.Electron.secureStorage.set('token', value);
if (!result.ok) {
console.error(`secureStorage.set failed [${result.error.code}]`, result.error.message);
return;
}
The playground centralizes this in playground/src/helpers/ipc.ts's unwrap() helper — logs the failure and returns undefined on ok: false, otherwise returns result.data.
React hooks (@devioarts/electron/react)
Thin hooks over window.Electron — no new IPC, no new capability, just ergonomics: typed access and auto-cleanup event subscriptions.
useElectron(): ElectronBridge— typed access towindow.Electron. Throws if used outside Electron (no bridge present).useElectronEvent<T>(subscribe, callback)— subscribes to anywindow.Electronon*event for the component's lifetime; the(callback) => unsubscribepattern is wrapped inuseEffectso the listener is removed automatically on unmount.useNativeTheme(): NativeThemeSnapshot | null— live native theme state, subscribes tonativeTheme.onUpdated.useShortcut(): string | null— latest global-shortcut event name fired since mount.useMenuAction(): MenuActionEvent | null— latest native menu action (app/context/dock/tray) fired since mount.useScreenEvent(): ScreenEventPayload | null— latest display/screen change event since mount.
import { useElectron, useNativeTheme, useElectronEvent } from '@devioarts/electron/react';
function TitleBar() {
const electron = useElectron();
const theme = useNativeTheme();
useElectronEvent(window.Electron.onShortcut, ({ event }) => {
if (event === 'open-search') setSearchOpen(true);
});
return (
<div>
<button onClick={() => electron.minimize()}>Minimize</button>
<span>{theme?.shouldUseDarkColors ? 'dark' : 'light'}</span>
</div>
);
}
Task examples
// Native OS notification (Notification Center / Action Center / libnotify) —
// not the web Notification API, so it works even when the window isn't focused.
const id = await window.Electron.notifications.show({ title: 'Export finished' });
const unsubscribe = window.Electron.notifications.on((event) => {
if (event.id === id && event.type === 'click') showExportFolder();
});
// Clipboard images — plain text copy/paste is already covered by the
// standard navigator.clipboard Web API, no bridge needed for that.
const pngDataUrl = await window.Electron.clipboard.readImage();
// Run a pre-configured Node.js helper script (see configuration/processes.md) —
// the renderer only ever names it by alias, never by file path.
const { id: taskId } = await window.Electron.utilityProcess.start('imageResizer');
window.Electron.utilityProcess.onMessage(({ id, message }) => {
if (id === taskId) console.log('progress from worker:', message);
});
// Taskbar/Dock progress indicator — e.g. during a long download or export.
await window.Electron.setProgressBar(0.42);
await window.Electron.setProgressBar(-1); // remove it
// Native OS drag of a file out of the window (e.g. onto the desktop or another
// app) — must be called from the renderer's own `dragstart` handler, and only
// works while that drag gesture is actually in progress.
someElement.addEventListener('dragstart', () => {
void window.Electron.startFileDrag({ file: '/path/to/export.pdf', icon: '/path/to/icon.png' });
});
Extending the bridge with your own channels
Spread createElectronBridge()'s result alongside your own properties before exposing:
// electron/preload.ts
import { contextBridge, ipcRenderer } from 'electron';
import { createElectronBridge } from '@devioarts/electron/preload';
contextBridge.exposeInMainWorld('Electron', {
...createElectronBridge(),
myCustomMethod: () => ipcRenderer.invoke('myApp:doSomething'),
});
Register the matching handler in electron/main.ts with the same trusted-origin check every built-in channel uses:
import { trustedIpcHandle } from '@devioarts/electron/main';
trustedIpcHandle('myApp:doSomething', (event, arg) => {
// ...
});
Then extend the type in electron-env.d.ts (scaffolded by dae init) so window.Electron.myCustomMethod is typed:
declare module '@devioarts/electron' {
interface ElectronBridge {
myCustomMethod: () => Promise<void>;
}
}
For a reusable capability shared across projects, prefer a plugin over ad-hoc additions like this.
Reference: API surface
Full grouped method list, for lookup once you know the concept you need:
| Group | Methods |
|---|---|
| System/window | quit, minimize, maximize, unmaximize, toggleMaximize, isMaximized, setFullscreen, isFullscreen, focus, reload, openDevTools, closeDevTools, getAppVersion, getPlatform, setBadgeCount, getBadgeCount, setProgressBar, startFileDrag |
updater |
checkForUpdate, downloadUpdate, quitAndInstall, on(event, callback) |
dialogs |
showOpenDialog, showSaveDialog, showMessageBox, showErrorBox |
secureStorage |
isEncryptionAvailable, getSelectedStorageBackend, set, get, remove, clear, keys, encryptString, decryptString |
protocols |
getConfiguredSchemes, isProtocolHandled, isDefaultProtocolClient, setAsDefaultProtocolClient, removeAsDefaultProtocolClient, openExternal |
session |
clearCache, clearStorageData, getUserAgent, setUserAgent, resolveProxy, setProxy, closeAllConnections, getCookies, setCookie, removeCookie |
downloads |
start, pause, resume, cancel, getActive, on(callback) |
print |
getPrinters, print, printToPDF |
desktopCapture |
getSources(options) |
autoLaunch |
isEnabled, setEnabled, getSettings |
nativeTheme |
get, setThemeSource, onUpdated(callback) |
windows |
create, list, focus, close, show, hide, setBounds, openExternal |
externalCommands |
run, start, kill, onOutput(callback), onExit(callback) |
clipboard |
readText, writeText, readImage, writeImage, clear, availableFormats |
notifications |
isSupported, show, close, on(callback) |
systemPreferences |
getAccentColor, getColor, getEffectiveAppearance, getMediaAccessStatus, askForMediaAccess |
crashReporter |
getLastCrashReport |
utilityProcess |
start, postMessage, kill, onMessage(callback), onExit(callback) |
| Deep link / shortcuts / menu | onDeepLink(callback), registerShortcut, unregisterShortcut, onShortcut(callback), showContextMenu, onMenuAction(callback) |
| Power | onPowerMonitorEvent(callback), getPowerMonitorIdleState, getPowerMonitorIdleTime, startPowerSaveBlocker, stopPowerSaveBlocker, isPowerSaveBlockerStarted |
| Screen | getAllDisplays, getPrimaryDisplay, getCursorScreenPoint, getCursorDisplay, onScreenEvent(callback) |
| Errors | onElectronError(callback) |
Next: Configuration to enable the opt-in features these methods unlock, or Plugins to add your own capability group in the same style.