Building Your First Electron App
Electron lets you build desktop apps with web technologies. That is the short version. If you know HTML, CSS, and JavaScript or TypeScript, Electron gives you a way to package that knowledge into a desktop application that can run on macOS, Windows, and Linux. The tradeoff is that Electron is not just "a website in a window." It has its own architecture, security concerns, packaging workflow, and performance considerations. The first thing to understand is how an Electron app is shaped.
The Mental Model
An Electron app has two main sides:
- the main process
- the renderer process The main process controls the desktop application itself. It can:
- create windows
- manage app lifecycle events
- access Node.js APIs
- talk to the operating system
- coordinate native features The renderer process is the web page shown inside a window. It handles:
- HTML
- CSS
- frontend JavaScript
- UI interactions
- browser-like rendering If you have built web apps before, the renderer process will feel familiar. The main process is the part that feels more like desktop app development.
A Tiny Electron Shape
A small Electron app usually has a file that creates a browser window. Conceptually:
const { app, BrowserWindow } = require("electron");
function createWindow() {
const window = new BrowserWindow({
width: 900,
height: 700,
});
window.loadFile("index.html");
}
app.whenReady().then(createWindow);
That is the core idea:
- Wait for Electron to be ready.
- Create a window.
- Load some HTML into that window. From there, the app grows around that basic structure.
Main Process vs Renderer Process
This separation is important. The renderer should not get unrestricted access to your computer just because it is displaying HTML. For example, imagine your renderer loads remote content or renders user-provided HTML. Giving that page full access to Node.js would be risky. A safer pattern is:
- keep privileged operations in the main process
- expose a small API through a preload script
- let the renderer ask for specific actions This keeps the boundary clearer. The renderer can say:
Save this document. The main process decides how that save operation actually touches the filesystem.
Preload Scripts
A preload script runs between the main process and renderer process. It is commonly used to expose a controlled API to the UI. Conceptually:
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("appApi", {
saveNote: (note) => ipcRenderer.invoke("save-note", note),
});
Then the renderer can call:
window.appApi.saveNote({
title: "Draft",
body: "Hello",
});
The point is not just convenience. It is separation. The UI gets the capabilities you intentionally expose, not everything.
What Should Your First App Be?
Pick something small. Good first Electron app ideas:
- Markdown note viewer
- local JSON editor
- project launcher
- clipboard utility
- tiny SQLite browser
- image metadata viewer Avoid starting with something that requires auto-update, cloud sync, accounts, complex menus, native integrations, and cross-platform packaging all at once. Your first goal should be understanding the app shape.
Common Mistakes
Mistake 1: Treating Electron like a normal website
Electron uses web technologies, but it is a desktop app runtime. That means you need to care about filesystem access, app lifecycle, menu behavior, packaging, and security boundaries.
Mistake 2: Giving the renderer too much power
Do not expose Node.js and native access casually. Keep privileged work in the main process and expose small APIs.
Mistake 3: Starting with packaging before the app works
Packaging matters, but it is not the first problem. Get a tiny app running locally first. Then worry about installers, icons, signing, and updates.
Where This Shows Up in Real Projects
Electron is useful when you want a desktop app but also want to reuse web UI skills. It is a good fit for:
- internal tools
- developer tools
- local-first utilities
- dashboards
- desktop companions for web apps
- apps that need filesystem access with a rich UI It is not automatically the right choice for every desktop app. If you need the lightest possible native app, a native stack may be better. If you need to move quickly with a web-style interface, Electron can be a practical choice.
Key Takeaways
- Electron apps have a main process and renderer processes.
- The main process owns app lifecycle and native access.
- The renderer displays the UI.
- Preload scripts help expose a small, controlled API.
Start with a small local app before solving packaging and updates.
Related Articles
Electron vs Native macOS Apps
- TypeScript for Python Developers
- What Is Bun and Where Does It Fit?