Browse docs
Make It Yours

Project Structure

Where everything lives, and the one rule about which process code belongs in.

Updated Aug 2026
On this page

Four top-level folders under src/, and one rule that decides which one your code goes in.

The rule

Can this code work without touching the operating system?

Yes: it belongs in the renderer, or in shared. No: it belongs in the main process, reached over an IPC channel.

Reading a file, showing a native dialog, registering a global shortcut, writing to the database, calling an API with a secret key: all main process. Everything a user looks at: renderer.

The folders

src/
  main/       Node.js. Windows, files, database, licensing, updates, tray, shortcuts.
  preload/    The only bridge between the two. One file. Read it once.
  renderer/   Your React app. Screens, hooks, contexts, styles, i18n.
  shared/     Types, Zod schemas, and the 45 UI components. Imported by both sides.
  features/   One folder per screen. This is where your product lives.

Inside main/, folders are named for what they do: db/, licensing/, updater/, telemetry/, security/, services/, ipc/.

The files you will open most

File What it decides
src/renderer/screens-registry.ts Which screens exist, in sidebar order
src/shared/ipc/channels.ts Every channel name, in one list
src/shared/ipc/types.ts The request and response shape of every channel
src/preload/preload.ts What the renderer is allowed to call
src/main/ipc/register.ts Which handler answers which channel
electron-builder.yml How the app is packaged and where updates come from
CLAUDE.md The architecture rules, written for AI coding tools

Adding a feature touches five places

The channel name, the types, the schema, the main handler, and the preload bridge. The generators write four of them:

npm run new:feature MyFeature
npm run new:ipc myfeature:doathing

Build Your First Screen walks the whole thing with a working example.

Why the preload file exists

The renderer runs sandboxed with contextIsolation on. It cannot reach Node.js, which means a compromised page in your app cannot read the user's disk.

The preload script is the one place that decides what crosses that boundary. It exposes a fixed list of functions on window.api and nothing else. If a capability is not in preload.ts, the renderer does not have it. That is the whole security model, and it is worth reading the file once so you know what your renderer can and cannot do.

If you use Claude Code, Cursor, or Copilot

Point it at CLAUDE.md first. It documents these rules, the five-place pattern, and the file-size conventions, so your agent adds code in the right place instead of inventing a new one.

Give your agent a codebase with opinions.

Electron 41 + React 19 + TypeScript desktop app boilerplate built for Claude Code, Cursor and Copilot. 950 lines of rules your agent reads first, so feature fifty looks like feature one.

Get it for $49 →