Electron Architecture Expert
Expert assistant for Electron desktop application architecture, Main/Renderer process design, IPC communication, security best practices, and application packaging.
How It Works Analyzes application requirements Designs secure Main/Renderer architecture Implements safe IPC communication patterns Provides packaging and distribution configuration Ensures security best practices Usage Scaffold New Project bash /mnt/skills/user/electron-architect/scripts/scaffold-project.sh [project-name] [ui-framework] [package-manager]
Arguments:
project-name - Name of the project (default: my-electron-app) ui-framework - UI framework: vanilla, react, svelte, vue (default: vanilla) package-manager - Package manager: pnpm, npm, yarn (default: pnpm)
Examples:
bash /mnt/skills/user/electron-architect/scripts/scaffold-project.sh my-app bash /mnt/skills/user/electron-architect/scripts/scaffold-project.sh my-app react bash /mnt/skills/user/electron-architect/scripts/scaffold-project.sh my-app svelte pnpm
Security defaults:
nodeIntegration: false contextIsolation: true sandbox: true Documentation Resources
Official Documentation:
Electron: https://www.electronjs.org/docs/latest/ Electron Forge: https://www.electronforge.io/ electron-builder: https://www.electron.build/ Project Structure src/ ├── main/ │ ├── main.ts # Main process entry │ ├── ipc/ # IPC handlers │ │ └── file-handlers.ts │ ├── services/ # Backend services │ │ └── database.ts │ └── menu.ts # Application menu ├── preload/ │ └── preload.ts # Context bridge ├── renderer/ # UI (React/Svelte/Vue) │ ├── App.tsx │ └── components/ └── shared/ └── types.ts # Shared type definitions
Security Configuration BrowserWindow Settings // main.ts - Secure configuration const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, // Disable Node.js contextIsolation: true, // Enable context isolation sandbox: true, // Sandbox mode preload: path.join(__dirname, 'preload.js'), webSecurity: true, // Enforce same-origin } });
Preload Script Pattern // preload.ts - Safe API exposure import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electronAPI', { // One-way: Renderer → Main saveFile: (content: string) => ipcRenderer.invoke('file:save', content),
// One-way: Main → Renderer onUpdateAvailable: (callback: (version: string) => void) => ipcRenderer.on('update-available', (_, version) => callback(version)),
// Request-response pattern openFile: () => ipcRenderer.invoke('dialog:openFile'), });
// Type declaration for renderer
declare global {
interface Window {
electronAPI: {
saveFile: (content: string) => Promise
Main Process Handlers // main/ipc/file-handlers.ts import { ipcMain, dialog } from 'electron'; import { readFile, writeFile } from 'fs/promises';
export function registerFileHandlers() { ipcMain.handle('dialog:openFile', async () => { const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'Text', extensions: ['txt', 'md'] }] }); if (canceled) return null; return readFile(filePaths[0], 'utf-8'); });
ipcMain.handle('file:save', async (_, content: string) => { const { canceled, filePath } = await dialog.showSaveDialog({}); if (canceled || !filePath) return false; await writeFile(filePath, content); return true; }); }
IPC Communication Patterns Pattern 1: Invoke (Request-Response) // Renderer const data = await window.electronAPI.fetchData(id);
// Main ipcMain.handle('fetch-data', async (event, id) => { return await database.get(id); });
Pattern 2: Send/On (Fire-and-Forget) // Main → Renderer mainWindow.webContents.send('notification', message);
// Renderer window.electronAPI.onNotification((msg) => showToast(msg));
Pattern 3: Two-Way Events // Renderer sends, awaits Main response const result = await window.electronAPI.processFile(path);
Packaging Configuration Electron Forge { "config": { "forge": { "packagerConfig": { "asar": true, "icon": "./assets/icon" }, "makers": [ { "name": "@electron-forge/maker-squirrel" }, { "name": "@electron-forge/maker-dmg" }, { "name": "@electron-forge/maker-deb" } ] } } }
Present Results to User
When providing Electron solutions:
Always follow security best practices Provide complete IPC communication examples Consider cross-platform compatibility Include TypeScript types for the API Note Electron version differences Troubleshooting
"require is not defined"
nodeIntegration is correctly disabled Use preload script with contextBridge
"Cannot access window.electronAPI"
Check preload script path is correct Verify contextIsolation is true Ensure contextBridge.exposeInMainWorld is called
"IPC message not received"
Verify channel names match exactly Check if handler is registered before window loads Use invoke for async responses