Docs

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 to window.Electron. Throws if used outside Electron (no bridge present).
  • useElectronEvent<T>(subscribe, callback) — subscribes to any window.Electron on* event for the component's lifetime; the (callback) => unsubscribe pattern is wrapped in useEffect so the listener is removed automatically on unmount.
  • useNativeTheme(): NativeThemeSnapshot | null — live native theme state, subscribes to nativeTheme.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.

Last updated on July 17, 2026