Loading...
Loading...
Guide AI agents through Electron app development with React including security patterns, type-safe IPC, React integration, packaging with code signing, and testing. Keywords: electron, electron-vite, electron-forge, contextBridge, IPC, security, react, packaging, code signing, notarization, playwright, desktop app.
npx skill4agent add jwynia/agent-skills electron-best-practices// preload.ts - SECURE pattern
contextBridge.exposeInMainWorld('electronAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs'),
saveFile: (content: string) => ipcRenderer.invoke('save-file', content),
onUpdateCounter: (callback: (value: number) => void) => {
const handler = (_event: IpcRendererEvent, value: number) => callback(value);
ipcRenderer.on('update-counter', handler);
return () => ipcRenderer.removeListener('update-counter', handler);
}
});'self'type IpcChannelMap = {
'load-prefs': { args: []; return: UserPreferences };
'save-file': { args: [content: string]; return: { success: boolean } };
};export const appRouter = t.router({
greeting: t.procedure
.input(z.object({ name: z.string() }))
.query(({ input }) => `Hello, ${input.name}!`),
});message{ success, data, error }src/
├── main/ # Main process (Node.js environment)
│ ├── index.ts
│ └── ipc/ # IPC handlers
├── preload/ # Secure bridge via contextBridge
│ ├── index.ts
│ └── index.d.ts # TypeScript declarations for exposed APIs
└── renderer/ # React application (pure web, no Node access)
├── src/
└── index.htmluseEffect(() => {
const cleanup = window.electronAPI.onUpdateCounter((value) => {
setCount(value);
});
return cleanup;
}, []);| Category | Prefer | Avoid |
|---|---|---|
| Security | | |
| IPC | | |
| Preload | Typed function wrappers | Exposing raw |
| Build tool | electron-vite | webpack-based toolchains |
| Packaging | Electron Forge | Manual packaging |
| State | Zustand + electron-store | Redux for simple apps |
| Testing | Playwright E2E | Spectron (deprecated) |
| Updates | electron-updater | Manual update checks |
| Signing | CI-integrated code signing | Unsigned releases |
| CSP | HTTP headers, | No CSP |
| Error handling | Result type | Raw Error across IPC |
| Multi-window | Main process as state hub | Direct window-to-window |
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
contextIsolation: true,
sandbox: true,
nodeIntegration: false,
},
});export function registerFileHandlers(): void {
ipcMain.handle('save-file', async (_event, content: string) => {
try {
await fs.writeFile(filePath, content);
return { success: true, data: filePath };
} catch (err) {
return { success: false, error: (err as Error).message };
}
});
}| Anti-Pattern | Problem | Solution |
|---|---|---|
| XSS escalates to full RCE | Keep disabled (default) |
Exposing | Full IPC access from renderer | Wrap in contextBridge functions |
Missing | Renderer accesses preload scope | Keep enabled (default since Electron 12) |
| No code signing | OS security warnings, Gatekeeper blocks | Sign and notarize for all platforms |
| Preload has full Node.js access | Enable sandbox (default since Electron 20) |
| Unvalidated IPC arguments | Injection attacks from renderer | Validate with Zod or manual checks |
| Network-exposed local server | Always bind to |
| Missing CSP headers | Script injection vectors | Set strict CSP via HTTP headers |
| No IPC error serialization | Lost error context across boundary | Use Result type pattern |
| Spectron for testing | Deprecated, Electron 13 max | Use Playwright |
references/security/security-checklist.mddeno run --allow-read scripts/analyze-security.ts <path> [options]
Options:
--strict Enable all checks
--json Output JSON for CI
-h, --help Show help
Examples:
# Analyze a project
deno run --allow-read scripts/analyze-security.ts ./src
# Strict mode for CI pipeline
deno run --allow-read scripts/analyze-security.ts ./src --strict --jsondeno run --allow-read --allow-write scripts/scaffold-electron-app.ts [options]
Options:
--name <name> App name (required)
--path <path> Target directory (default: ./)
--with-react Include React setup
--with-trpc Include electron-trpc
--with-tests Include Playwright tests
Examples:
# Basic app with React
deno run --allow-read --allow-write scripts/scaffold-electron-app.ts \
--name "my-app" --with-react
# Full setup with trpc and tests
deno run --allow-read --allow-write scripts/scaffold-electron-app.ts \
--name "my-app" --with-react --with-trpc --with-testsdeno run --allow-read --allow-write scripts/generate-ipc-types.ts [options]
Options:
--handlers <path> Path to IPC handler files
--output <path> Output path for type definitions
--validate Validate existing types match handlers
Examples:
# Generate types from handlers
deno run --allow-read --allow-write scripts/generate-ipc-types.ts \
--handlers ./src/main/ipc --output ./src/preload/ipc-types.d.ts
# Validate types in CI
deno run --allow-read scripts/generate-ipc-types.ts \
--handlers ./src/main/ipc --validatereferences/security/context-isolation.mdreferences/security/csp-and-permissions.mdreferences/security/security-checklist.mdreferences/ipc/typed-ipc.mdreferences/ipc/electron-trpc.mdreferences/ipc/error-serialization.mdreferences/architecture/project-structure.mdreferences/architecture/process-separation.mdreferences/architecture/multi-window-state.mdreferences/integration/react-patterns.mdreferences/integration/state-management.mdreferences/packaging/code-signing.mdreferences/packaging/auto-updates.mdreferences/packaging/bundle-optimization.mdreferences/packaging/ci-cd-patterns.mdreferences/testing/playwright-e2e.mdreferences/testing/unit-testing.mdreferences/testing/test-structure.mdreferences/tooling/electron-vite.mdreferences/tooling/electron-forge.mdreferences/tooling/tauri-comparison.mdassets/templates/main-process.ts.mdassets/templates/preload-script.ts.mdassets/templates/ipc-handler.ts.mdassets/templates/react-root.tsx.mdassets/configs/electron-vite.config.ts.mdassets/configs/forge.config.js.mdassets/configs/tsconfig.json.mdassets/configs/playwright.config.ts.mdassets/examples/typed-ipc-example.mdassets/examples/multi-window-example.md