Electron ist 2026 noch immer das meistgenutzte Framework für Cross-Platform-Desktop-Apps
mit Web-Technologien. VS Code, Slack, Figma, Discord — alle basieren auf Electron.
Mit Claude Code lassen sich komplexe Electron-Applikationen mit Main-Process-Logik,
IPC-Kommunikation, nativen APIs und automatischen Updates deutlich schneller entwickeln.
Dieser Guide zeigt die sechs zentralen Bausteine einer modernen Electron-App.
Voraussetzungen: Node.js 20+, npm 10+, TypeScript-Grundkenntnisse.
Electron-Version in diesem Guide: Electron 30 mit
electron-vite 2.x und React 18.
1. Electron-Architektur: Main vs. Renderer Process
Electron trennt strikt zwischen zwei Prozessen. Der Main Process läuft
in Node.js und steuert Fenster, Menus und native OS-Funktionen. Der Renderer Process
ist eine Chromium-Instanz und rendert die React-UI. Die Brücke zwischen beiden ist das
Preload-Script über contextBridge.
| Main Process |
Renderer Process |
Preload Script |
| Node.js Full Access |
Browser-Sandbox |
Sichere Brücke |
| BrowserWindow, Menu |
React, DOM, CSS |
contextBridge API |
| ipcMain.handle() |
ipcRenderer.invoke() |
exposeInMainWorld() |
| fs, path, os |
fetch, localStorage |
Typen-sichere API |
| app, dialog, shell |
window.electronAPI |
Validierung/Filter |
main.ts — BrowserWindow erstellen
// src/main/main.ts — Electron Main Process
import { app, BrowserWindow, Menu, shell, nativeImage } from 'electron'
import { join } from 'path'
import { registerIpcHandlers } from './ipc-handlers'
import { buildAppMenu } from './menu'
let mainWindow: BrowserWindow | null = null
function createWindow(): void {
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
minWidth: 800,
minHeight: 600,
show: false, // Verhindert weißes Flash
titleBarStyle: 'hiddenInset', // macOS-spezifisch
icon: nativeImage.createFromPath(
join(__dirname, '../resources/icon.png')
),
webPreferences: {
preload: join(__dirname, '../preload/preload.js'),
contextIsolation: true, // PFLICHT seit Electron 12+
nodeIntegration: false, // Node.js NICHT im Renderer!
sandbox: true, // Zusätzliche Sicherheit
webSecurity: true,
},
})
// Fenster erst zeigen wenn DOM bereit (verhindert flackern)
mainWindow.once('ready-to-show', () => {
mainWindow!.show()
if (process.env.NODE_ENV === 'development') {
mainWindow!.webContents.openDevTools()
}
})
// URL laden — Dev: Vite Dev Server / Prod: lokale HTML-Datei
if (process.env.ELECTRON_RENDERER_URL) {
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL)
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
// Externe Links im System-Browser öffnen
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https:')) shell.openExternal(url)
return { action: 'deny' }
})
}
app.whenReady().then(() => {
createWindow()
registerIpcHandlers()
Menu.setApplicationMenu(buildAppMenu())
app.on('activate', () => {
// macOS: Fenster neu erstellen wenn Dock-Icon geklickt
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
// macOS behält App aktiv bis explizit beendet
if (process.platform !== 'darwin') app.quit()
})
Wichtige BrowserWindow-Optionen 2026
- contextIsolation: true — Pflicht! Renderer kann nicht auf Node.js-Globals zugreifen
- nodeIntegration: false — Node.js nur im Main Process, nie im Renderer
- sandbox: true — Chromium-Renderer vollständig sandboxed
- show: false + ready-to-show — Verhindert weißes Flash beim Start
- titleBarStyle: hiddenInset — Native macOS-Titlebar mit Traffic Lights
preload.ts — contextBridge-Typen
// src/preload/preload.ts — Sichere Brücke Main ↔ Renderer
import { contextBridge, ipcRenderer } from 'electron'
// Typen-Definition für window.electronAPI im Renderer
export type ElectronAPI = {
readFile: (path: string) => Promise<string>
writeFile: (path: string, content: string) => Promise<void>
selectFile: (options?: FileDialogOptions) => Promise<string | null>
showNotification: (title: string, body: string) => void
getAppVersion: () => Promise<string>
onUpdateAvailable: (callback: (version: string) => void) => void
platform: string
}
contextBridge.exposeInMainWorld('electronAPI', {
readFile: (path: string) =>
ipcRenderer.invoke('fs:read-file', path),
writeFile: (path: string, content: string) =>
ipcRenderer.invoke('fs:write-file', { path, content }),
selectFile: (options?) =>
ipcRenderer.invoke('dialog:open-file', options),
showNotification: (title: string, body: string) =>
ipcRenderer.send('notification:show', { title, body }),
getAppVersion: () =>
ipcRenderer.invoke('app:get-version'),
onUpdateAvailable: (callback) =>
ipcRenderer.on('update:available', (_event, version) => callback(version)),
// Statische Werte direkt übergeben (kein IPC nötig)
platform: process.platform,
} satisfies ElectronAPI)
2. IPC-Kommunikation: Main ↔ Renderer
IPC (Inter-Process Communication) ist das Herzstück jeder Electron-App.
Das moderne Pattern seit Electron 13 ist ipcMain.handle im Main Process
und ipcRenderer.invoke im Preload — beide arbeiten mit Promises,
kein Callback-Hell.
IPC-Pattern-Empfehlung 2026: Immer invoke/handle
für bidirektionale Kommunikation. send/on nur für
Fire-and-Forget-Nachrichten (z.B. Notifications). Niemals sendSync —
das blockiert den Renderer-Thread!
ipc-handlers.ts — Alle Handler registrieren
// src/main/ipc-handlers.ts
import { ipcMain, app, dialog, Notification, BrowserWindow } from 'electron'
import { promises as fs } from 'fs'
import { join } from 'path'
export function registerIpcHandlers(): void {
// ── Dateisystem ────────────────────────────────────────
ipcMain.handle('fs:read-file', async (_event, path: string) => {
// Sicherheits-Check: Nur erlaubte Pfade
if (!isAllowedPath(path)) {
throw new Error(`Zugriff verweigert: ${path}`)
}
return fs.readFile(path, 'utf-8')
})
ipcMain.handle(
'fs:write-file',
async (_event, { path, content }: { path: string; content: string }) => {
if (!isAllowedPath(path)) throw new Error(`Zugriff verweigert: ${path}`)
await fs.writeFile(path, content, 'utf-8')
}
)
// ── Dialog ─────────────────────────────────────────────
ipcMain.handle('dialog:open-file', async (_event, options = {}) => {
const win = BrowserWindow.getFocusedWindow()
const result = await dialog.showOpenDialog(win!, {
properties: ['openFile'],
filters: options.filters ?? [{ name: 'Alle Dateien', extensions: ['*'] }],
})
return result.canceled ? null : result.filePaths[0]
})
ipcMain.handle('dialog:save-file', async (_event, options = {}) => {
const win = BrowserWindow.getFocusedWindow()
const result = await dialog.showSaveDialog(win!, {
defaultPath: options.defaultPath ?? 'datei.txt',
})
return result.canceled ? null : result.filePath
})
// ── App-Infos ───────────────────────────────────────────
ipcMain.handle('app:get-version', () => app.getVersion())
ipcMain.handle('app:get-path', (_event, name: string) => app.getPath(name as any))
// ── Notification (Fire & Forget) ────────────────────────
ipcMain.on('notification:show', (_event, { title, body }) => {
if (Notification.isSupported()) {
new Notification({ title, body }).show()
}
})
}
// Sicherheits-Helper: Nur Pfade in userData/Downloads erlaubt
function isAllowedPath(filePath: string): boolean {
const allowedRoots = [
app.getPath('userData'),
app.getPath('downloads'),
app.getPath('documents'),
]
return allowedRoots.some(root => filePath.startsWith(root))
}
React-Hook für IPC-Aufrufe
// src/renderer/hooks/useElectron.ts
import { useCallback } from 'react'
import type { ElectronAPI } from '../../preload/preload'
// TypeScript: window.electronAPI typen
declare global {
interface Window { electronAPI: ElectronAPI }
}
export function useElectron() {
const selectAndReadFile = useCallback(async () => {
const path = await window.electronAPI.selectFile({
filters: [{ name: 'Textdateien', extensions: ['txt', 'md', 'json'] }],
})
if (!path) return null
const content = await window.electronAPI.readFile(path)
return { path, content }
}, [])
const saveFile = useCallback(async (path: string, content: string) => {
await window.electronAPI.writeFile(path, content)
window.electronAPI.showNotification('Gespeichert', `${path} wurde gespeichert.`)
}, [])
return { selectAndReadFile, saveFile, platform: window.electronAPI.platform }
}
IPC
IPC-Channels: Namenskonvention
Verwende das Format namespace:action für alle IPC-Channels:
fs:read-file, dialog:open-file, app:get-version,
update:check. Dadurch bleiben Channels organisiert und skalierbar.
Dokumentiere alle Channels in einer zentralen ipc-channels.ts-Datei
mit Typexporten.
3. Vite + React Integration mit electron-vite
electron-vite ist 2026 der Standard für Electron-Build-Setups.
Es konfiguriert automatisch separate Vite-Instanzen für Main Process, Preload
und Renderer — mit Hot Module Replacement (HMR) im Renderer, TypeScript-Support
und optimierten Produktions-Bundles.
Projekt-Setup mit electron-vite
# Neues Projekt erstellen
npm create electron-vite@latest meine-app -- --template react-ts
cd meine-app
npm install
npm run dev # Startet App + HMR
# Projektstruktur:
# src/
# main/ → Main Process (Node.js)
# preload/ → Preload Script (contextBridge)
# renderer/ → React App (Chromium)
# resources/ → Icons, native Assets
# electron.vite.config.ts
electron.vite.config.ts
// electron.vite.config.ts
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()], // Node-Deps extern halten
build: {
rollupOptions: {
input: { index: resolve('src/main/main.ts') },
},
},
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
rollupOptions: {
input: { index: resolve('src/preload/preload.ts') },
},
},
},
renderer: {
resolve: {
alias: {
'@': resolve('src/renderer/src'),
'@components': resolve('src/renderer/src/components'),
'@hooks': resolve('src/renderer/src/hooks'),
},
},
plugins: [react()],
server: {
port: 5173,
strictPort: true,
},
build: {
outDir: 'out/renderer',
rollupOptions: {
input: { index: resolve('src/renderer/index.html') },
},
},
},
})
HMR-Workflow im Development
// package.json Scripts
{
"scripts": {
"dev": "electron-vite dev", // Startet Vite Dev Server + Electron
"build": "electron-vite build", // Produktions-Bundle
"start": "electron-vite preview", // Preview des Produktions-Builds
"dist": "npm run build && electron-builder",
"typecheck": "tsc --noEmit"
}
}
HMR-Vorteile mit electron-vite
- React-Komponenten-Änderungen sofort ohne App-Neustart sichtbar
- Main-Process-Änderungen triggern automatischen Electron-Neustart
- Preload-Änderungen triggern Renderer-Reload (contextBridge)
- TypeScript-Fehler sofort in der Konsole sichtbar
- Source Maps für alle drei Prozesse in DevTools
React-App im Renderer: App.tsx
// src/renderer/src/App.tsx
import { useState } from 'react'
import { useElectron } from '@hooks/useElectron'
import { FileEditor } from '@components/FileEditor'
export default function App() {
const [file, setFile] = useState<{ path: string; content: string } | null>(null)
const { selectAndReadFile, saveFile, platform } = useElectron()
const handleOpen = async () => {
const result = await selectAndReadFile()
if (result) setFile(result)
}
return (
<div className="app">
<header>
<h1>Meine Desktop-App</h1>
<span className="platform-badge">{platform}</span>
<button onClick={handleOpen}>Datei öffnen</button>
</header>
{file && (
<FileEditor
path={file.path}
content={file.content}
onSave={content => saveFile(file.path, content)}
/>
)}
</div>
)
}
4. Native Features: Tray, Dialoge, Notifications
Electron bietet Zugriff auf alle nativen Betriebssystem-APIs —
System Tray, Dateidialoge, Desktop-Notifications, Clipboard und Shell-Integration.
Diese machen den Unterschied zwischen einer Web-App und einer echten Desktop-Applikation.
Native
Native API-Übersicht
- app.getPath(name) — userData, downloads, documents, temp, desktop
- dialog.showOpenDialog — Datei-Auswahl-Dialog nativ
- dialog.showMessageBox — Native Message-Dialoge (Alert, Confirm)
- Notification — OS-Desktop-Notifications (Windows Toast, macOS, Linux)
- Tray — System-Tray-Icon mit Context Menu
- shell.openExternal — URLs im Standard-Browser öffnen
- clipboard — Lesen/Schreiben der Zwischenablage
- nativeImage — Plattform-spezifische Icons
System Tray mit Context Menu
// src/main/tray.ts
import { Tray, Menu, nativeImage, BrowserWindow, app } from 'electron'
import { join } from 'path'
export function createTray(mainWindow: BrowserWindow): Tray {
const icon = nativeImage.createFromPath(
join(__dirname, '../../resources/tray-icon.png')
).resize({ width: 16, height: 16 })
const tray = new Tray(icon)
const contextMenu = Menu.buildFromTemplate([
{
label: 'Fenster anzeigen',
click: () => {
mainWindow.show()
mainWindow.focus()
},
},
{ type: 'separator' },
{
label: 'Synchronisierung',
submenu: [
{ label: 'Jetzt synchronisieren', click: () => mainWindow.webContents.send('sync:trigger') },
{ label: 'Automatisch', type: 'checkbox', checked: true },
],
},
{ type: 'separator' },
{
label: 'Beenden',
click: () => app.quit(),
accelerator: process.platform === 'darwin' ? 'Cmd+Q' : 'Alt+F4',
},
])
tray.setContextMenu(contextMenu)
tray.setToolTip('Meine App — läuft im Hintergrund')
// Doppelklick zeigt Fenster (Windows-Konvention)
tray.on('double-click', () => mainWindow.show())
return tray
}
Native App-Menu mit Tastaturkürzeln
// src/main/menu.ts
import { Menu, MenuItemConstructorOptions, app, shell, BrowserWindow } from 'electron'
export function buildAppMenu(): Menu {
const isMac = process.platform === 'darwin'
const template: MenuItemConstructorOptions[] = [
// macOS-spezifisches App-Menu
...(isMac ? [{
label: app.name,
submenu: [
{ role: 'about' as const },
{ type: 'separator' as const },
{ role: 'hide' as const },
{ role: 'hideOthers' as const },
{ type: 'separator' as const },
{ role: 'quit' as const },
],
}] : []),
{
label: 'Datei',
submenu: [
{
label: 'Neue Datei',
accelerator: 'CmdOrCtrl+N',
click: () => BrowserWindow.getFocusedWindow()?.webContents.send('file:new'),
},
{
label: 'Öffnen...',
accelerator: 'CmdOrCtrl+O',
click: () => BrowserWindow.getFocusedWindow()?.webContents.send('file:open'),
},
{
label: 'Speichern',
accelerator: 'CmdOrCtrl+S',
click: () => BrowserWindow.getFocusedWindow()?.webContents.send('file:save'),
},
{ type: 'separator' },
isMac ? { role: 'close' as const } : { role: 'quit' as const },
],
},
{
label: 'Hilfe',
submenu: [
{
label: 'Dokumentation',
click: () => shell.openExternal('https://agentic-movers.com/docs'),
},
{ role: 'toggleDevTools' },
],
},
]
return Menu.buildFromTemplate(template)
}
5. Auto-Update mit electron-updater
Automatische Updates sind für Desktop-Apps entscheidend. electron-updater
(Teil von electron-builder) unterstützt GitHub Releases, S3 und eigene Update-Server.
Im Main Process prüft autoUpdater beim Start und benachrichtigt den
Renderer über verfügbare Updates.
Wichtig: Auto-Updates funktionieren nur bei signierten und notarisierten
Apps (macOS) bzw. signierten Installern (Windows NSIS). Im Development-Modus
wird Auto-Update automatisch deaktiviert.
updater.ts — Update-Logik im Main Process
// src/main/updater.ts
import { autoUpdater } from 'electron-updater'
import { BrowserWindow, dialog } from 'electron'
import log from 'electron-log'
export function setupAutoUpdater(mainWindow: BrowserWindow): void {
// Logging aktivieren
autoUpdater.logger = log
log.transports.file.level = 'info'
// Update-URL (GitHub Releases)
autoUpdater.setFeedURL({
provider: 'github',
owner: 'meinorg',
repo: 'meine-app',
private: false,
})
// Events → Renderer weiterleiten
autoUpdater.on('update-available', (info) => {
log.info(`Update verfügbar: ${info.version}`)
mainWindow.webContents.send('update:available', info.version)
})
autoUpdater.on('update-not-available', () => {
log.info('App ist aktuell.')
})
autoUpdater.on('download-progress', (progress) => {
mainWindow.webContents.send('update:progress', Math.round(progress.percent))
mainWindow.setProgressBar(progress.percent / 100) // Windows Taskbar-Progress
})
autoUpdater.on('update-downloaded', (info) => {
log.info(`Update ${info.version} heruntergeladen`)
mainWindow.setProgressBar(-1) // Taskbar-Progress entfernen
const response = dialog.showMessageBoxSync(mainWindow, {
type: 'info',
buttons: ['Jetzt neu starten', 'Später'],
title: 'Update verfügbar',
message: `Version ${info.version} wurde heruntergeladen.`,
detail: 'Jetzt neu starten um das Update zu installieren?',
})
if (response === 0) autoUpdater.quitAndInstall()
})
autoUpdater.on('error', (err) => {
log.error('Auto-Updater Fehler:', err)
mainWindow.webContents.send('update:error', err.message)
})
// Beim Start nach Updates suchen (kurze Verzögerung)
setTimeout(() => {
if (process.env.NODE_ENV !== 'development') {
autoUpdater.checkForUpdatesAndNotify()
}
}, 3000)
}
Update-Banner in React
// src/renderer/src/components/UpdateBanner.tsx
import { useState, useEffect } from 'react'
export function UpdateBanner() {
const [updateVersion, setUpdateVersion] = useState<string | null>(null)
const [progress, setProgress] = useState<number | null>(null)
useEffect(() => {
window.electronAPI.onUpdateAvailable((version) => setUpdateVersion(version))
// Progress-Event direkt über ipcRenderer (via erweitertes Preload)
return () => { /* cleanup listeners */ }
}, [])
if (!updateVersion) return null
return (
<div className="update-banner">
<span>Update {updateVersion} verfügbar</span>
{progress !== null && (
<div className="progress-bar">
<div style={{ width: `${progress}%` }} />
</div>
)}
</div>
)
}
6. Build & Code-Signing: Windows, macOS, Linux
electron-builder erzeugt plattform-spezifische Distributionen.
Code-Signing ist auf macOS (Notarisierung Pflicht seit macOS Catalina) und
Windows (SmartScreen-Filter umgehen) entscheidend für eine professionelle
User-Experience ohne Sicherheitswarnungen.
electron-builder.yml
# electron-builder.yml
appId: com.meinefirma.meineapp
productName: Meine Desktop App
copyright: Copyright © 2026 Meine Firma GmbH
# Build-Artefakte Verzeichnis
directories:
output: release
# Dateien die in die App eingebunden werden
files:
- out/**/*
- resources/**/*
- "!**/*.{map,ts}"
# Auto-Update: publish auf GitHub Releases
publish:
- provider: github
owner: meinorg
repo: meine-app
# macOS Build + Code-Signing
mac:
category: public.app-category.productivity
target:
- target: dmg
arch: [x64, arm64] # Universal Binary
- target: zip
hardenedRuntime: true
gatekeeperAssess: false
entitlements: resources/entitlements.mac.plist
entitlementsInherit: resources/entitlements.mac.plist
# macOS Notarisierung (Apple ID + App-spezifisches Passwort)
afterSign: scripts/notarize.js
# Windows Build + NSIS Installer + Code-Signing
win:
target: nsis
certificateFile: ${env.WIN_CERT_FILE} # aus Umgebungsvariable
certificatePassword: ${env.WIN_CERT_PASS}
signingHashAlgorithms: [sha256]
nsis:
oneClick: false
allowToChangeInstallationDirectory: true
createDesktopShortcut: true
runAfterFinish: true
# Linux: AppImage + Debian-Paket
linux:
target:
- AppImage
- deb
category: Utility
maintainer: info@meinefirma.de
desktop:
Name: Meine Desktop App
Comment: Produktivitäts-Tool 2026
macOS Notarisierung: notarize.js
// scripts/notarize.js — Wird von electron-builder aufgerufen
const { notarize } = require('@electron/notarize')
module.exports = async function (context) {
const { electronPlatformName, appOutDir } = context
if (electronPlatformName !== 'darwin') return
const appName = context.packager.appInfo.productFilename
const appBundleId = 'com.meinefirma.meineapp'
console.log(`Notarisierung: ${appName}.app`)
await notarize({
tool: 'notarytool', // Xcode 13+: notarytool
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID, // Apple Developer ID
appleIdPassword: process.env.APPLE_ID_PASS, // App-spezifisches Passwort
teamId: process.env.APPLE_TEAM_ID,
})
console.log('Notarisierung erfolgreich!')
}
GitHub Actions CI/CD Build-Pipeline
# .github/workflows/release.yml
name: Release Build
on:
push:
tags: ['v*']
jobs:
build:
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Dependencies installieren
run: npm ci
- name: TypeScript prüfen
run: npm run typecheck
- name: App bauen & publishen
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
WIN_CERT_FILE: ${{ secrets.WIN_CERTIFICATE_FILE }}
WIN_CERT_PASS: ${{ secrets.WIN_CERTIFICATE_PASSWORD }}
CSC_LINK: ${{ secrets.MAC_CERTS }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }}
run: npm run dist -- --publish always
Build
Code-Signing Checkliste
- macOS: Apple Developer Program ($99/Jahr), Developer ID Application Zertifikat, Hardened Runtime aktivieren, Notarisierung mit notarytool (nicht altool)
- Windows: EV Code Signing Zertifikat (empfohlen) oder OV, NSIS-Installer signieren, SmartScreen-Reputationsaufbau dauert einige Wochen
- Linux: AppImage benötigt kein Code-Signing, aber GPG-Signierung der Release-Artefakte empfohlen
- Universal Binary macOS:
arch: [x64, arm64] für Apple Silicon + Intel
electron-vite Build-Optimierungen
// src/main/main.ts — Produktions-Optimierungen
// 1. Splash Screen bei langen Ladezeiten
const splash = new BrowserWindow({
width: 400, height: 300,
frame: false, transparent: true,
alwaysOnTop: true,
})
splash.loadFile('resources/splash.html')
// 2. Main Window nach Splash schließen
mainWindow.once('ready-to-show', () => {
splash.destroy()
mainWindow!.show()
})
// 3. Session-Cache für Assets konfigurieren
mainWindow.webContents.session.setPreloads([
join(__dirname, '../preload/preload.js')
])
// 4. Zoom-Level sperren (Accessibility bewahren)
mainWindow.webContents.on('did-finish-load', () => {
mainWindow!.webContents.setZoomLevel(0)
})
// 5. Fensterposition persistieren
const bounds = store.get('windowBounds', { width: 1280, height: 800 })
mainWindow.setBounds(bounds)
mainWindow.on('close', () => store.set('windowBounds', mainWindow!.getBounds()))
Fazit: Electron 2026 mit Claude Code
Electron ist trotz seines Rufes als “zu schwer” nach wie vor die
pragmatischste Wahl für Cross-Platform-Desktop-Apps wenn das Team Web-Skills
mitbringt. Mit electron-vite, React 18 und
TypeScript ist der Development-Workflow 2026 deutlich schneller
als noch vor drei Jahren.
Claude Code beschleunigt die Electron-Entwicklung besonders in diesen Bereichen:
IPC-Handler typen-sicher aufbauen, contextBridge-APIs konsistent halten,
plattform-spezifische Conditional-Logik für macOS/Windows/Linux,
und den oft komplexen Build/Code-Signing-Prozess in CI/CD abbilden.
Stack-Empfehlung 2026
- Electron 30+ — Chromium 124+, Node.js 20+
- electron-vite 2.x — Build-System + HMR
- React 18 + TypeScript 5.4+ — Renderer UI
- electron-updater — Auto-Update (Teil von electron-builder)
- electron-builder 25+ — Packaging + Code-Signing
- electron-store — Persistente App-Einstellungen
- electron-log — Dateibasiertes Logging für alle Prozesse
Alternativen zu Electron: Tauri (Rust-basiert, deutlich kleiner,
kein Chromium-Bundle) ist 2026 für neue Projekte eine starke Alternative
wenn Bunde-Size und RAM-Verbrauch kritisch sind. Für Teams mit React-Erfahrung
bleibt Electron die produktivere Wahl.
Desktop-Apps mit KI entwickeln?
Starte deinen kostenlosen Trial und lass Claude Code deine nächste
Electron-App aufbauen — von der Architektur bis zum signierten Installer.
Kostenlos ausprobieren →