Claude-skill-registry electron-scaffold
Scaffold a native-looking, effective Electron app with best practices baked in. Creates a production-ready Electron application with security hardening, modern tooling, proper IPC patterns, auto-updates, native UI elements, and optimal build configuration. Use this skill when users want to start a new Electron project or modernize an existing one.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/electron-scaffold" ~/.claude/skills/majiayu000-claude-skill-registry-electron-scaffold && rm -rf "$T"
skills/data/electron-scaffold/SKILL.mdElectron Application Scaffolding
Create production-ready Electron applications with security, performance, and native platform integration best practices built in from the start.
When to Use This Skill
Use this skill when:
- User wants to create a new Electron desktop application
- User needs to scaffold an Electron project with modern best practices
- User wants a native-looking cross-platform desktop app
- User mentions "Electron app", "desktop app", "cross-platform app", or similar
- User wants to modernize an existing Electron project structure
Prerequisites Check
Before scaffolding, verify:
-
Node.js: Check Node.js version (18.x or higher recommended)
node --version -
npm or yarn: Verify package manager is available
npm --version -
Git: Ensure git is available for version control
git --version
Architecture Decision Points
1. Build Tooling Choice
Ask the user which build system they prefer (or recommend based on use case):
Electron Forge (Recommended for most projects)
- All-in-one tooling solution
- Built-in TypeScript support
- Easy plugin system
- Great for: Most new projects, teams wanting batteries-included setup
Electron Builder
- Highly configurable
- Excellent multi-platform packaging
- Auto-update support
- Great for: Complex build requirements, specific packaging needs
Vite + Electron
- Fastest development experience
- Modern ESM-first approach
- Hot module replacement
- Great for: Modern web frameworks (React, Vue, Svelte), speed-focused development
2. Frontend Framework
Determine the UI framework:
- Vanilla JS/TypeScript: Lightest, full control
- React: Most popular, large ecosystem
- Vue: Progressive, easy to learn
- Svelte: Smallest bundle, compile-time framework
- Angular: Enterprise-ready, opinionated
3. TypeScript vs JavaScript
Strongly recommend TypeScript for:
- Better IDE support and autocomplete
- Catch errors at compile time
- Better maintainability
- Electron API typing support
Workflow
Step 1: Project Initialization
Based on tooling choice, initialize the project:
For Electron Forge (Recommended):
npm init electron-app@latest <app-name> -- --template=webpack-typescript
For Vite + Electron:
npm create @quick-start/electron <app-name>
For custom setup: Create package.json with proper dependencies (see templates).
Step 2: Project Structure Setup
Create a well-organized project structure:
<app-name>/ ├── src/ │ ├── main/ # Main process │ │ ├── main.ts # Entry point │ │ ├── ipc/ # IPC handlers │ │ ├── menu.ts # Native menu │ │ └── tray.ts # System tray (if needed) │ ├── preload/ # Preload scripts │ │ └── preload.ts # Context bridge │ ├── renderer/ # Renderer process │ │ ├── index.html │ │ ├── index.ts │ │ └── styles/ │ └── shared/ # Shared types/utilities │ └── types.ts ├── assets/ # Icons, images ├── resources/ # Build resources ├── dist/ # Build output ├── package.json ├── tsconfig.json └── electron-builder.yml # or forge.config.js
Step 3: Security Configuration
CRITICAL: Implement security best practices from the start.
1. BrowserWindow Security Options:
const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { // Security: Use preload scripts instead of nodeIntegration nodeIntegration: false, // Security: Isolate context between web content and preload contextIsolation: true, // Security: Disable remote module enableRemoteModule: false, // Security: Use sandboxed renderer sandbox: true, // Preload script for safe IPC preload: path.join(__dirname, 'preload.js'), // Security: Disable web security only in development if needed webSecurity: true, // Security: Disable navigation allowRunningInsecureContent: false, }, });
2. Content Security Policy (CSP):
// In main process or HTML meta tag session.defaultSession.webRequest.onHeadersReceived((details, callback) => { callback({ responseHeaders: { ...details.responseHeaders, 'Content-Security-Policy': [ "default-src 'self'", "script-src 'self'", "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:", "connect-src 'self'", ].join('; '), }, }); });
3. Context Bridge (preload.ts):
import { contextBridge, ipcRenderer } from 'electron'; // Expose protected methods that allow the renderer process to use // the ipcRenderer without exposing the entire object contextBridge.exposeInMainWorld('electronAPI', { // Invoke pattern (request-response) getAppVersion: () => ipcRenderer.invoke('app:get-version'), // Send pattern (one-way) logMessage: (message: string) => ipcRenderer.send('log:message', message), // Listener pattern (for receiving events) onUpdateAvailable: (callback: (info: any) => void) => { ipcRenderer.on('update:available', (_event, info) => callback(info)); }, // Remove listener removeUpdateListener: () => { ipcRenderer.removeAllListeners('update:available'); }, });
4. IPC Security Pattern:
// main/ipc/handlers.ts import { ipcMain } from 'electron'; // Use invoke/handle pattern for request-response ipcMain.handle('app:get-version', async () => { return app.getVersion(); }); // Validate and sanitize all inputs ipcMain.handle('file:read', async (_event, filePath: string) => { // Validate path is within allowed directories const allowedDir = app.getPath('userData'); const resolvedPath = path.resolve(filePath); if (!resolvedPath.startsWith(allowedDir)) { throw new Error('Access denied'); } return fs.readFile(resolvedPath, 'utf-8'); });
Step 4: Native UI Elements
Create native-looking UI components:
1. Application Menu:
// main/menu.ts import { Menu, shell } from 'electron'; export function createApplicationMenu(mainWindow: BrowserWindow) { const template: MenuItemConstructorOptions[] = [ { label: 'File', submenu: [ { label: 'New', accelerator: 'CmdOrCtrl+N', click: () => mainWindow.webContents.send('file:new'), }, { type: 'separator' }, { role: 'quit' }, ], }, { label: 'Edit', submenu: [ { role: 'undo' }, { role: 'redo' }, { type: 'separator' }, { role: 'cut' }, { role: 'copy' }, { role: 'paste' }, ], }, { label: 'View', submenu: [ { role: 'reload' }, { role: 'forceReload' }, { role: 'toggleDevTools' }, { type: 'separator' }, { role: 'resetZoom' }, { role: 'zoomIn' }, { role: 'zoomOut' }, { type: 'separator' }, { role: 'togglefullscreen' }, ], }, { label: 'Help', submenu: [ { label: 'Learn More', click: async () => { await shell.openExternal('https://electronjs.org'); }, }, ], }, ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); }
2. System Tray (Optional):
// main/tray.ts import { Tray, Menu, nativeImage } from 'electron'; export function createTray(mainWindow: BrowserWindow) { const icon = nativeImage.createFromPath( path.join(__dirname, '../assets/tray-icon.png') ); const tray = new Tray(icon); const contextMenu = Menu.buildFromTemplate([ { label: 'Show App', click: () => { mainWindow.show(); }, }, { label: 'Quit', click: () => { app.quit(); }, }, ]); tray.setContextMenu(contextMenu); tray.setToolTip('My Electron App'); return tray; }
Step 5: Development Environment Setup
1. Hot Reload Configuration:
// main.ts const isDevelopment = process.env.NODE_ENV === 'development'; if (isDevelopment) { mainWindow.loadURL('http://localhost:5173'); // Vite dev server mainWindow.webContents.openDevTools(); } else { mainWindow.loadFile(path.join(__dirname, '../renderer/index.html')); }
2. Package.json Scripts:
{ "scripts": { "dev": "concurrently \"npm:dev:*\"", "dev:vite": "vite", "dev:electron": "electron .", "build": "npm run build:renderer && npm run build:main", "build:renderer": "vite build", "build:main": "tsc -p tsconfig.main.json", "package": "electron-builder", "package:all": "electron-builder -mwl", "lint": "eslint src --ext .ts,.tsx", "typecheck": "tsc --noEmit" } }
Step 6: Auto-Update Configuration
Implement automatic updates using electron-updater:
1. Install Dependencies:
npm install electron-updater
2. Update Configuration:
// main/updater.ts import { autoUpdater } from 'electron-updater'; export function setupAutoUpdater(mainWindow: BrowserWindow) { // Configure update server autoUpdater.setFeedURL({ provider: 'github', owner: 'your-username', repo: 'your-repo', }); // Check for updates on startup autoUpdater.checkForUpdatesAndNotify(); // Update events autoUpdater.on('update-available', (info) => { mainWindow.webContents.send('update:available', info); }); autoUpdater.on('update-downloaded', (info) => { mainWindow.webContents.send('update:downloaded', info); }); autoUpdater.on('error', (err) => { mainWindow.webContents.send('update:error', err); }); }
3. electron-builder Configuration:
# electron-builder.yml appId: com.yourcompany.yourapp productName: YourApp directories: output: dist buildResources: resources files: - src/**/* - package.json mac: category: public.app-category.productivity target: - dmg - zip hardenedRuntime: true gatekeeperAssess: false entitlements: resources/entitlements.mac.plist win: target: - nsis - portable publisherName: Your Company linux: target: - AppImage - deb category: Utility publish: provider: github owner: your-username repo: your-repo
Step 7: TypeScript Configuration
tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020", "DOM"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "resolveJsonModule": true, "outDir": "./dist", "rootDir": "./src", "types": ["node", "electron"] }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
Step 8: Build and Package
Development:
npm run dev
Production Build:
npm run build npm run package
Multi-platform Build:
npm run package:all
Best Practices Checklist
When scaffolding, ensure these are implemented:
Security
- Context isolation enabled
- Node integration disabled in renderer
- Preload script with context bridge
- Content Security Policy configured
- Input validation on all IPC handlers
- Sandbox mode enabled
- Web security enabled
- Navigation and redirect guards
Performance
- Lazy loading for renderer modules
- Background throttling configured
- Memory management for large datasets
- Efficient IPC patterns (batch updates)
- Webpack/Vite optimization
User Experience
- Native application menu
- Keyboard shortcuts (accelerators)
- Window state persistence
- Proper icon set (all sizes)
- Splash screen (optional)
- Error boundaries
- Loading states
Developer Experience
- TypeScript configured
- Hot reload working
- DevTools available in development
- ESLint and Prettier setup
- Git hooks with Husky (optional)
- Source maps enabled
Distribution
- Auto-update configured
- Code signing setup (platform-specific)
- Build scripts for all platforms
- Proper app metadata
- License file included
Error Handling Patterns
Main Process Errors
process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); // Log to file or error tracking service app.quit(); }); process.on('unhandledRejection', (reason) => { console.error('Unhandled Rejection:', reason); });
Renderer Process Errors
window.addEventListener('error', (event) => { window.electronAPI.logError({ message: event.error.message, stack: event.error.stack, }); }); window.addEventListener('unhandledrejection', (event) => { window.electronAPI.logError({ message: 'Unhandled Promise Rejection', reason: event.reason, }); });
Platform-Specific Considerations
macOS
- Use
icon format.icns - Implement dock menu
- Handle
event (reopen window)activate - Consider macOS-specific menu items (About, Preferences)
- Code signing required for distribution
Windows
- Use
icon format.ico - Handle Squirrel startup events
- Consider Windows toast notifications
- NSIS installer customization
- Code signing with certificate
Linux
- Use
icon format.png - Provide
file.desktop - Handle different package formats (deb, AppImage, snap)
- Test on multiple distributions
Example Scaffolds
Minimal TypeScript Setup
# Initialize with Forge npm init electron-app@latest my-app -- --template=webpack-typescript # Add security defaults # Add IPC patterns # Configure build
React + TypeScript + Vite
# Create with Vite template npm create @quick-start/electron my-app -- --template react-ts # Add security hardening # Configure auto-update # Add native menus
Production-Ready Full Setup
- Complete security configuration
- Auto-update with GitHub releases
- Native UI elements (menu, tray)
- Error tracking
- Analytics (optional)
- Crash reporting
- Multi-platform build pipeline
Tips for Success
- Start Secure: Don't add security later—build it in from day one
- Type Everything: Use TypeScript for both main and renderer processes
- Test IPC Early: IPC issues are easier to debug early
- Platform Test: Test on all target platforms regularly
- Monitor Bundle Size: Keep renderer bundle optimized
- Document IPC Contract: Maintain API documentation between processes
- Version Control: Git ignore
,dist/
,node_modules/.env - Use Process Manager: Handle main process crashes gracefully
- Implement Logging: Structured logging helps debug production issues
- Plan Updates: Design update strategy before first release
Common Pitfalls to Avoid
- ❌ Enabling
without good reasonnodeIntegration - ❌ Skipping context isolation
- ❌ Loading remote content without validation
- ❌ Exposing entire IPC renderer to web content
- ❌ Ignoring security warnings in console
- ❌ Not testing on all target platforms
- ❌ Hardcoding file paths (use
)app.getPath() - ❌ Forgetting to handle window state persistence
- ❌ Not implementing proper error boundaries
- ❌ Skipping code signing for distribution
Quick Start Command
For most users, recommend this command:
# Create app with TypeScript and Webpack npm init electron-app@latest <app-name> -- --template=webpack-typescript # Then apply security hardening, native UI, and build configuration
Reference Files
For detailed Electron API examples and configuration templates, see:
- Security best practicesreferences/electron-security.md
- IPC communication patternsreferences/ipc-patterns.md
- Build and packaging configurationreferences/build-config.md
- Automated scaffolding scriptscripts/scaffold.sh
Post-Scaffold Checklist
After scaffolding, guide the user to:
- ✅ Review and customize
metadatapackage.json - ✅ Add application icons (all platforms)
- ✅ Configure code signing certificates
- ✅ Set up GitHub repository for auto-updates
- ✅ Test hot reload and development workflow
- ✅ Build for all target platforms
- ✅ Test update mechanism
- ✅ Review security settings
- ✅ Add error tracking (Sentry, etc.)
- ✅ Create user documentation
Version Compatibility
This skill targets:
- Electron: v28+ (latest stable)
- Node.js: v18+ LTS
- TypeScript: v5+
- Electron Forge: v7+
- Electron Builder: v24+
Always check the latest Electron documentation for breaking changes.