Agent skill
electron-best-practices
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.
Install this agent skill to your Project
npx add-skill https://github.com/jwynia/agent-skills/tree/main/skills/tech/development/tooling/electron-best-practices
Metadata
Additional technical details for this skill
- mode
- assistive
- type
- utility
- author
- agent-skills
- domain
- development
- version
- 1.0
SKILL.md
Electron + React Best Practices
Guide AI agents in building secure, production-ready Electron applications with React. This skill provides security patterns, type-safe IPC communication, project setup guidance, packaging and code signing workflows, and tools for analysis, scaffolding, and type generation.
When to Use This Skill
Use this skill when:
- Generating Electron main, preload, or renderer process code
- Configuring electron-vite or Electron Forge
- Setting up IPC communication between processes
- Implementing security patterns (contextBridge, sandbox, CSP)
- Packaging, signing, and notarizing desktop applications
- Testing Electron apps with Playwright
- Designing multi-window architectures
Do NOT use this skill when:
- Building Tauri apps (different paradigm, use Tauri-specific guidance)
- Building pure web apps with no desktop requirements
- Targeting Electron versions below 20 (security defaults differ)
- Using non-React renderer frameworks (use framework-specific skills)
Core Principles
1. Security First Architecture
Modern Electron security relies on three defaults that became standard in Electron 20+: context isolation, sandbox mode, and nodeIntegration disabled. Disabling any of them allows XSS attacks to escalate to full remote code execution. All main-renderer communication must flow through contextBridge:
// 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);
}
});
Set Content Security Policy via HTTP headers for apps loading local files, restricting script sources to 'self'.
2. Type-Safe IPC Communication
The invoke/handle pattern is preferred over send/on for request-response communication, providing proper async/await semantics and error propagation. For typed channels, use a mapped type pattern:
type IpcChannelMap = {
'load-prefs': { args: []; return: UserPreferences };
'save-file': { args: [content: string]; return: { success: boolean } };
};
For complex applications, electron-trpc provides full type safety using tRPC's router pattern with Zod validation:
export const appRouter = t.router({
greeting: t.procedure
.input(z.object({ name: z.string() }))
.query(({ input }) => `Hello, ${input.name}!`),
});
Error handling across the IPC boundary requires attention because Electron only serializes the message property of Error objects. Wrap responses in a { success, data, error } result type to preserve full error context.
3. Modern Project Setup
The recommended stack uses electron-vite for development and Electron Forge for packaging. electron-vite provides a unified configuration managing main, preload, and renderer processes with sub-second dev server startup and instant HMR. Electron Forge uses first-party Electron packages for signing and notarization.
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.html
4. React Integration Patterns
React 18's concurrent features work normally in Electron's Chromium-based renderer. Strict Mode's double-invocation of effects catches IPC listener leaks that would otherwise cause memory issues. Always return cleanup functions from effects that register IPC listeners:
useEffect(() => {
const cleanup = window.electronAPI.onUpdateCounter((value) => {
setCount(value);
});
return cleanup;
}, []);
For multi-window applications, the main process should serve as the single source of truth for shared state. Use electron-store for persistence combined with IPC broadcasting so any window's mutation updates all others.
Quick Reference
| Category | Prefer | Avoid |
|---|---|---|
| Security | contextBridge.exposeInMainWorld() |
nodeIntegration: true |
| IPC | invoke/handle pattern |
send/on for request-response |
| Preload | Typed function wrappers | Exposing raw ipcRenderer |
| 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, 'self' only |
No CSP |
| Error handling | Result type {success, data, error} |
Raw Error across IPC |
| Multi-window | Main process as state hub | Direct window-to-window |
Code Generation Guidelines
When generating Electron code, follow these patterns:
BrowserWindow Creation
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
contextIsolation: true,
sandbox: true,
nodeIntegration: false,
},
});
Always enable contextIsolation and sandbox. Never enable nodeIntegration. The preload path must resolve to the built output location.
IPC Handler Module
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 };
}
});
}
Group related handlers into modules. Use the result type pattern for all return values. Validate all arguments received from the renderer process.
Common Anti-Patterns
Avoid these patterns when generating Electron code:
| Anti-Pattern | Problem | Solution |
|---|---|---|
nodeIntegration: true |
XSS escalates to full RCE | Keep disabled (default) |
Exposing ipcRenderer directly |
Full IPC access from renderer | Wrap in contextBridge functions |
Missing contextIsolation |
Renderer accesses preload scope | Keep enabled (default since Electron 12) |
| No code signing | OS security warnings, Gatekeeper blocks | Sign and notarize for all platforms |
BrowserWindow without sandbox |
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 |
0.0.0.0 server binding |
Network-exposed local server | Always bind to 127.0.0.1 |
| 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 |
See references/security/security-checklist.md for the full security audit checklist.
Scripts Reference
analyze-security.ts
Analyze Electron projects for security misconfigurations:
deno 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 --json
scaffold-electron-app.ts
Scaffold a new Electron + React project with secure defaults:
deno 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-tests
generate-ipc-types.ts
Generate TypeScript type definitions from IPC handler files:
deno 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 --validate
Additional Resources
Security
references/security/context-isolation.md- contextBridge and isolation patternsreferences/security/csp-and-permissions.md- Content Security Policy configurationreferences/security/security-checklist.md- Full security audit checklist
IPC Communication
references/ipc/typed-ipc.md- Typed channel map patternsreferences/ipc/electron-trpc.md- tRPC integration for full type safetyreferences/ipc/error-serialization.md- Result types across IPC boundary
Architecture
references/architecture/project-structure.md- Directory organizationreferences/architecture/process-separation.md- Main, preload, and renderer rolesreferences/architecture/multi-window-state.md- Shared state across windows
React Integration
references/integration/react-patterns.md- useEffect cleanup, Strict Modereferences/integration/state-management.md- Zustand and electron-store patterns
Packaging & Distribution
references/packaging/code-signing.md- Platform-specific signing workflowsreferences/packaging/auto-updates.md- electron-updater configurationreferences/packaging/bundle-optimization.md- Size reduction techniquesreferences/packaging/ci-cd-patterns.md- GitHub Actions matrix builds
Testing
references/testing/playwright-e2e.md- Playwright Electron supportreferences/testing/unit-testing.md- Jest/Vitest multi-project configurationreferences/testing/test-structure.md- Test organization patterns
Tooling
references/tooling/electron-vite.md- Build tool configurationreferences/tooling/electron-forge.md- Packaging and distributionreferences/tooling/tauri-comparison.md- When to choose Tauri instead
Templates
assets/templates/main-process.ts.md- Main process starter templateassets/templates/preload-script.ts.md- Preload script with contextBridgeassets/templates/ipc-handler.ts.md- IPC handler module templateassets/templates/react-root.tsx.md- React root component template
Configuration Examples
assets/configs/electron-vite.config.ts.md- electron-vite configurationassets/configs/forge.config.js.md- Electron Forge configurationassets/configs/tsconfig.json.md- TypeScript configuration presetsassets/configs/playwright.config.ts.md- Playwright Electron test config
Complete Examples
assets/examples/typed-ipc-example.md- End-to-end typed IPC walkthroughassets/examples/multi-window-example.md- Multi-window state management
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
document-to-narration
Convert written documents to narrated video scripts with TTS audio and word-level timing. Use when preparing essays, blog posts, or articles for video narration. Outputs scene files, audio, and VTT with precise word timestamps. Keywords: narration, voiceover, TTS, scenes, audio, timing, video script, spoken.
shadcn-layouts
Generate correct shadcn/Tailwind layouts by applying CSS mental models. This skill should be used when the user asks to 'create a shadcn layout', 'fix layout issues', 'debug CSS height problems', 'make scrolling work', or has issues with Tailwind flex/grid. Keywords: shadcn, Tailwind, layout, CSS, flex, grid, height, scroll, overflow.
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Provides analysis tools for auditing existing designs and generation tools for creating color palettes, typography systems, design tokens, and component templates. Supports React, Vue, Svelte, and vanilla HTML/CSS. Use when building web components, pages, or applications. Keywords: design, UI, frontend, CSS, components, palette, typography, tokens, accessibility.
react-pwa
pwa-development
Implement Progressive Web App features for React and Svelte projects. This skill should be used when the user asks to 'make a PWA', 'add offline support', 'create a service worker', 'fix caching issues', or wants installable web apps. Keywords: PWA, service worker, offline, manifest, caching, installable, Workbox, vite-pwa.
mastra-hono
Develop AI agents, tools, and workflows with Mastra v1 Beta and Hono servers. This skill should be used when creating Mastra agents, defining tools with Zod schemas, building workflows with step data flow, setting up Hono API servers with Mastra adapters, or implementing agent networks. Keywords: mastra, hono, agent, tool, workflow, AI, LLM, typescript, API, MCP.
Didn't find tool you were looking for?