A minimal foundation for building Electron applications with React, TypeScript, and Vite.
The project uses Electron directly. It does not use electron-vite, vite-plugin-electron, or Electron Forge's Vite plugin. The build and development workflow stays visible in the repository instead of being hidden behind an Electron-specific wrapper.
This starter provides the application infrastructure. It does not prescribe routing, state management, databases, authentication, telemetry, or product architecture.
Electron's process boundaries are kept explicit:
src/mainowns application lifecycle, windows, IPC handlers, and privileged operations.src/preloadexposes a narrow API to the renderer throughcontextBridge.src/renderercontains the React/Vite app.src/sharedcontains IPC contracts and types shared across processes.
Each process has a separate Vite configuration:
vite.config.tsbuilds the React renderer.vite.main.config.tsbuilds the Electron main process.vite.preload.config.tsbuilds the preload script.
Build output is written to dist/:
dist/
├── main/
├── preload/
└── renderer/
Source is organized like this:
src/
├── main/
│ └── index.ts
├── preload/
│ ├── index.d.ts
│ └── index.ts
├── renderer/
│ ├── index.html
│ ├── public/
│ └── src/
└── shared/
└── ipc.ts
- Node.js
>=22.18.0 - npm
Install dependencies:
npm installStart the development environment:
npm run devThis starts the Vite renderer server, watches the main and preload processes, and launches Electron. Renderer changes use HMR. Main-process changes restart Electron, while preload changes reload the renderer. Stopping the command also stops its child processes.
npm run dev # Start the complete development environment
npm run dev:renderer # Start only the renderer in a browser
npm run typecheck # Check TypeScript
npm run lint # Check code with Oxlint
npm run lint:fix # Apply safe Oxlint fixes
npm run format # Format files with Oxfmt
npm run format:check # Check formatting without changing files
npm run fix # Apply safe lint fixes and format files
npm run build # Build main, preload, and renderer
npm start # Run Electron from an existing production build
npm run package # Build and create an unpacked application
npm run make # Build and create platform distributablesOxlint uses its built-in defaults. Extend oxlint.config.ts as project requirements evolve. Oxfmt uses the starter author's preferred defaults in oxfmt.config.ts; adapt them to the project's conventions when needed.
Forge writes packaged applications and distributable files to out/.
Electron Forge is used only for distribution. It does not control the development server or compile the application source.
The current makers produce:
- Windows: Squirrel installer
- macOS: ZIP and DMG
- Linux: deb and RPM packages
Create distributables for the current platform:
npm run makeCreate macOS distributables explicitly:
npm run make -- --platform=darwinSome distributables require platform-specific tools and should be built on their target operating system. Code signing, macOS notarization, and publishing are not configured yet.
The current setup includes:
- renderer sandboxing
- context isolation
- disabled Node.js integration in the renderer
- a narrow, typed
contextBridgeAPI - IPC sender and argument validation
- navigation and new-window restrictions
- a renderer Content Security Policy
- a custom production protocol instead of
file:// - ASAR packaging
- restrictive Electron fuses for packaged applications
The renderer does not receive direct access to ipcRenderer, Node.js, the filesystem, or other privileged Electron APIs. Add new capabilities through a typed preload API and validate every request in the main process.
Electron-specific Vite wrappers reduce setup work, but they also own important parts of the development and build workflow. This starter keeps those parts as ordinary scripts and Vite configuration files that can be read, changed, and debugged directly.
Vite builds the renderer, main process, and preload script through separate configurations. The separation keeps their targets and module formats clear without adding another compiler such as esbuild.
scripts/dev.mjs coordinates Vite, Electron, rebuilds, restarts, and shutdown. The renderer still uses the normal vite.config.ts, with its app root set to src/renderer.
Forge handles packaging, installers, Electron fuses, and future signing or publishing work. It is not involved in the application development loop.
IPC channel names, arguments, results, and the renderer-facing API are defined centrally. The included ping method is a small example of the pattern new application APIs should follow.
The starter deliberately excludes application-level libraries and architecture. Separate variants can add tools such as Drizzle without making them requirements for every Electron application.
React Compiler is not enabled by default. Applications can add it when its optimization benefits justify the additional compilation work.