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.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "electron-scaffold" with this command: npx skills add chrisvoncsefalvay/claude-skills/chrisvoncsefalvay-claude-skills-electron-scaffold

Electron 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:

  1. Node.js: Check Node.js version (18.x or higher recommended)

    node --version
    
  2. npm or yarn: Verify package manager is available

    npm --version
    
  3. 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 .icns icon format
  • Implement dock menu
  • Handle activate event (reopen window)
  • Consider macOS-specific menu items (About, Preferences)
  • Code signing required for distribution

Windows

  • Use .ico icon format
  • Handle Squirrel startup events
  • Consider Windows toast notifications
  • NSIS installer customization
  • Code signing with certificate

Linux

  • Use .png icon format
  • Provide .desktop file
  • 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

  1. Start Secure: Don't add security later—build it in from day one
  2. Type Everything: Use TypeScript for both main and renderer processes
  3. Test IPC Early: IPC issues are easier to debug early
  4. Platform Test: Test on all target platforms regularly
  5. Monitor Bundle Size: Keep renderer bundle optimized
  6. Document IPC Contract: Maintain API documentation between processes
  7. Version Control: Git ignore dist/, node_modules/, .env
  8. Use Process Manager: Handle main process crashes gracefully
  9. Implement Logging: Structured logging helps debug production issues
  10. Plan Updates: Design update strategy before first release

Common Pitfalls to Avoid

  • ❌ Enabling nodeIntegration without good reason
  • ❌ 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:

  • references/electron-security.md - Security best practices
  • references/ipc-patterns.md - IPC communication patterns
  • references/build-config.md - Build and packaging configuration
  • scripts/scaffold.sh - Automated scaffolding script

Post-Scaffold Checklist

After scaffolding, guide the user to:

  1. ✅ Review and customize package.json metadata
  2. ✅ Add application icons (all platforms)
  3. ✅ Configure code signing certificates
  4. ✅ Set up GitHub repository for auto-updates
  5. ✅ Test hot reload and development workflow
  6. ✅ Build for all target platforms
  7. ✅ Test update mechanism
  8. ✅ Review security settings
  9. ✅ Add error tracking (Sentry, etc.)
  10. ✅ 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.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

security-reviewer

No summary provided by upstream source.

Repository SourceNeeds Review
Security

ux-audit

No summary provided by upstream source.

Repository SourceNeeds Review
492-jezweb
Security

senior-security

No summary provided by upstream source.

Repository SourceNeeds Review
Security

ux-audit-rethink

No summary provided by upstream source.

Repository SourceNeeds Review