Hello World
This guide builds a minimal Electrobun app by hand, without a template, so you can see exactly what each piece is for. The main process runs on Cottontail, the default TypeScript runtime. Every runtime has its own version of this walkthrough: Bun, Zig, Rust, Go, and Odin.
If you just want a running app, hutch electrobun init my-app --template=hello-world gets you the same result in one command — this guide
is for understanding what that command sets up.
1. Create the project
mkdir my-appcd my-appCreate package.json:
{ "name": "my-app", "private": true, "type": "module", "devDependencies": { "@types/bun": "latest" }}There is deliberately no electrobun npm dependency in this direct-Hutch
example. Hutch’s built-in resolver owns ordinary JavaScript dependencies and
hutch.lock; Hutch supplies the versioned Electrobun SDK through
.hutch/devkit.
Create hutch.config.ts for project tasks:
export default { scripts: { install: ["hutch", "install", "--frozen-lockfile"], dev: ["hutch", "electrobun", "dev", "--watch"], build: ["hutch", "electrobun", "build", "--env=stable"], },};Hutch reads scripts and package-manager overrides only from this file. With no
packageManager field, the install task reads package.json, resolves
packages with Hutch’s built-in resolver, and owns hutch.lock. See
Hutch for the boundary and external-manager option.
Create tsconfig.json so editors and TypeScript resolve the package-free SDK
facade that Hutch projects during sync:
{ "extends": "./.hutch/devkit/tsconfig.json"}2. Add a webview
This is your app’s UI — plain HTML, rendered in a native webview. Create
src/mainview/index.html:
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <title>Hello Electrobun</title> </head> <body> <h1>Hello from Electrobun</h1> </body></html>Anything you’d put in a web page works here: CSS, TypeScript, React, whatever you like. For hello world, a heading is plenty.
3. Add the main process
The main process is the privileged side of your app — it runs on Cottontail,
not in the webview, and it’s what creates windows. Create src/bun/index.ts:
import { BrowserWindow } from "electrobun/main";
new BrowserWindow({ title: "Hello Electrobun", url: "views://mainview/index.html", frame: { width: 800, height: 600, x: 200, y: 200, },});The views:// URL is Electrobun’s scheme for assets bundled into the app —
this one points at the HTML file from the previous step, wherever the bundle
ends up on disk.
4. Configure the build
The last piece is telling Hutch how these files become an app. Create
electrobun.config.ts:
import type { ElectrobunConfig } from "electrobun";
export default { app: { name: "My App", identifier: "dev.example.my-app", version: "0.0.1", }, build: { mainProcess: "cottontail", cottontail: { entrypoint: "src/bun/index.ts", }, copy: { "src/mainview/index.html": "views/mainview/index.html", }, },} satisfies ElectrobunConfig;Reading it top to bottom: app names and identifies the application,
mainProcess selects Cottontail as the runtime, entrypoint points at the
main process you just wrote, and copy places the HTML file into the bundle at
the path the views:// URL expects. With no explicit electrobun.version, a
direct Hutch sync resolves the active channel and then reuses that projected
core and SDK until the next sync.
5. Run the app
hutch installhutch electrobun synchutch run devThe first command uses Hutch’s built-in resolver and creates hutch.lock. Sync
resolves an exact Electrobun release under ~/.hutch and creates
.hutch/devkit; future clean checkouts can use hutch run install with the
committed lockfile. Hutch then builds the app, launches it, and a window titled “Hello Electrobun”
opens with your heading in it. Leave it running — edits to watched source
files trigger a rebuild. Press Ctrl+C to stop.
That’s the whole loop: a main process that opens windows, HTML that fills them, and a config that binds the two. From here, the natural next steps are talking between the two sides with RPC (Main Process API) and building real UI (Creating UI).