Electron — a framework for creating desktop applications using web technologies (HTML, CSS, JS).
System design context: Electron runs your React app in a Chromium browser window with access to Node.js APIs. It has two processes: the main process (Node.js, manages windows and OS integration) and the renderer process (your React app). Security is critical — never expose Node.js APIs directly to the renderer. Use a preload script as a secure bridge between the two.
Example project structure:
my-app/
electron/
main.ts # Electron main process
preload.ts # Preload
src/
App.tsx # React component
index.tsx # Entry point
package.json
Main process (electron/main.ts):
1import { app, BrowserWindow } from "electron";2import path from "path";34function createWindow() {5 const win = new BrowserWindow({6 width: 1200,7 height: 800,8 webPreferences: {9 preload: path.join(__dirname, "preload.js"),10 contextIsolation: true, // Security: isolate contexts11 nodeIntegration: false, // Security: disable Node in renderer12 },13 });1415 // In dev — local server16 if (process.env.NODE_ENV === "development") {17 win.loadURL("http://localhost:5173");18 } else {19 // In production — built files20 win.loadFile(path.join(__dirname, "../dist/index.html"));21 }22}2324app.whenReady().then(createWindow);
Preload (secure bridge between main and renderer):
1import { contextBridge, ipcRenderer } from "electron";23contextBridge.exposeInMainWorld("electronAPI", {4 readFile: (path) => ipcRenderer.invoke("read-file", path),5 writeFile: (path, data) => ipcRenderer.invoke("write-file", path, data),6 openDialog: () => ipcRenderer.invoke("open-dialog"),7});
Usage in React:
1function App() {2 const handleOpenFile = async () => {3 const path = await window.electronAPI.openDialog();4 const content = await window.electronAPI.readFile(path);5 setFileContent(content);6 };78 return <button onClick={handleOpenFile}>Open file</button>;9}
Common pitfalls:
nodeIntegration: true — exposes Node.js to untrusted content (security risk).close event to prevent window from just hiding.electron-builder with asar to optimize.Alternatives: Tauri (smaller size, Rust backend), Neutralinojs.