Skip to content

BrowserView

BrowserView is Electrobun’s main-process wrapper around a native or CEF webview. Every BrowserWindow creates one initial view, available as window.webview. Create additional views when a window needs independently positioned web content. In the native SDKs there is no view class: createWebview returns a u32 id and every operation is a Core call keyed by that id.

import { BrowserView, BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({
title: "Multiple views",
url: "views://shell/index.html",
frame: { width: 1000, height: 700 },
});
const view = new BrowserView({
windowId: win.id,
url: "views://details/index.html",
frame: { x: 320, y: 0, width: 680, height: 700 },
autoResize: false,
});
void view;

The rest of this page documents the TypeScript class. The native SDKs expose the same webview verb set as Core calls — see the mapping at the end of the page.

The constructor accepts Partial<BrowserViewOptions>.

Option Type Default Purpose
windowId number 0 Native parent window ID.
hostWebviewId number none Host view for an <electrobun-webview> child.
url string | null null URL to load.
html string | null null HTML string to load instead of url.
preload string | null null Inline JavaScript or a bundled views:// script URL.
viewsRoot string | null null Override for the bundled views root.
allowedProtocols { views?: boolean; appData?: boolean } { views: true, appData: false } Grant this webview access to Electrobun’s filesystem-backed URL schemes.
renderer "native" | "cef" Platform build default Webview renderer.
partition string | null null Persistent storage/session partition.
frame { x: number; y: number; width: number; height: number } { x: 0, y: 0, width: 800, height: 600 } Position inside the parent window.
autoResize boolean true Resize with the parent window.
rpc RPC instance generated empty RPC Typed main-process transport.
navigationRules string | null null Serialized navigation policy.
sandbox boolean false Disable RPC for untrusted content.
startTransparent boolean false Create the native layer transparent.
startPassthrough boolean false Create with input passthrough enabled.
spellCheck boolean false Enable native spell checking where supported.

allowedProtocols controls filesystem access for this view. Enabling appData permits reads from the app’s userData directory through appdata://, including after navigation to remote content. See Bundled and app-owned assets for examples and protocol boundaries.

On Windows WebView2, unsafe, uppercase, Unicode, reserved, or over-80-character partition names now map to hashed profile directories. Existing safe lowercase ASCII names retain their paths; other names start in new directories without migrating or deleting their old data. See the Electrobun 2.0.2 migration notes.

import { BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({
title: "View controls",
url: "views://mainview/index.html",
});
const view = win.webview;
view.loadURL("views://details/index.html");
view.loadHTML("<!doctype html><title>Inline content</title><h1>Hello</h1>");
view.executeJavascript("document.documentElement.dataset.host = 'electrobun'");
view.setNavigationRules(["views://details/*"]);
view.openDevTools();
view.closeDevTools();
view.toggleDevTools();
view.setPageZoom(1.25);
const zoom = view.getPageZoom();
const spellCheckChanged = view.setSpellCheck(true);
void zoom;
void spellCheckChanged;

executeJavascript() does not return the evaluated value. Use typed RPC when the browser must return data to the main process.

import { BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({
title: "Find",
url: "views://mainview/index.html",
});
win.webview.findInPage("Electrobun", {
forward: true,
matchCase: false,
});
win.webview.stopFindInPage();

Instance events cover navigation, readiness, and downloads. Event payloads are currently typed as unknown.

import { BrowserView, BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({
title: "Events",
url: "views://mainview/index.html",
});
win.webview.on("dom-ready", (event: unknown) => {
console.log("DOM ready", event);
});
win.webview.on("did-navigate", (event: unknown) => {
console.log("Navigation finished", event);
});
win.webview.on("download-completed", (event: unknown) => {
console.log("Download complete", event);
});
const stopWatchingCreatedViews = BrowserView.on("created", (createdView) => {
console.log("BrowserView created", createdView.id);
});
stopWatchingCreatedViews();

Supported instance event names are will-navigate, did-navigate, did-navigate-in-page, did-commit-navigation, dom-ready, download-started, download-progress, download-completed, and download-failed.

Define the shared schema in a module imported by both contexts. The main process uses BrowserView.defineRPC; the browser uses Electroview.defineRPC.

import {
BrowserView,
BrowserWindow,
type RPCSchema,
} from "electrobun/main";
export type AppRPC = {
bun: RPCSchema<{
requests: {
greet: {
params: { name: string };
response: { message: string };
};
};
messages: {};
}>;
webview: RPCSchema<{
requests: {};
messages: {
statusChanged: { online: boolean };
};
}>;
};
const rpc = BrowserView.defineRPC<AppRPC>({
handlers: {
requests: {
greet: ({ name }) => ({ message: `Hello, ${name}` }),
},
messages: {},
},
});
const win = new BrowserWindow({
title: "Typed RPC",
url: "views://mainview/index.html",
rpc,
});
rpc.send.statusChanged({ online: true });
void win;

The browser-side half is documented under Electroview.

import { BrowserView, BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({
title: "View ownership",
url: "views://mainview/index.html",
});
const existing = BrowserView.getById(win.webview.id);
const allViews = BrowserView.getAll();
if (existing) {
const wrapped = BrowserView.ensureWrapped(existing.id, {
windowId: win.id,
});
const adopted = BrowserView.adoptExisting(existing.id, {
windowId: win.id,
});
void wrapped;
void adopted;
}
void allViews;

ensureWrapped() and adoptExisting() are advanced APIs for native views that already exist. Calling remove() destroys a view and disconnects its RPC transport; repeated calls are safe.

  • Content: loadURL, loadHTML, executeJavascript, setNavigationRules, setSpellCheck.
  • Developer tools and find: openDevTools, closeDevTools, toggleDevTools, findInPage, stopFindInPage.
  • Display: setPageZoom, getPageZoom.
  • Lifecycle and events: on, remove, ptr.
  • Static ownership: getById, getAll, ensureWrapped, adoptExisting, on, off, and defineRPC.

Zig, Rust, Go, and Odin expose the webview verb set procedurally on Core, keyed by the u32 webview id createWebview returns. Only naming style differs per language:

TypeScript Zig / Odin Rust Go
view.loadURL(url) loadURLInWebview(id, url) load_url_in_webview(id, url) LoadURLInWebview(id, url)
view.loadHTML(html) loadHTMLInWebview(id, html) load_html_in_webview(id, html) LoadHTMLInWebview(id, html)
frame / autoResize option resizeWebview(id, frame, masks_json) resize_webview(id, frame, masks_json) ResizeWebview(id, frame, masksJSON)
startTransparent / startPassthrough options setWebviewTransparent / setWebviewPassthrough / setWebviewHidden set_webview_transparent / set_webview_passthrough / set_webview_hidden SetWebviewTransparent / SetWebviewPassthrough / SetWebviewHidden
view.setSpellCheck(b) setWebviewSpellCheck(id, b) set_webview_spell_check(id, b) SetWebviewSpellCheck(id, b)
view.setNavigationRules(rules) setWebviewNavigationRules(id, rules_json) set_webview_navigation_rules(id, rules_json) SetWebviewNavigationRules(id, rulesJSON)
view.findInPage / stopFindInPage webviewFindInPage / webviewStopFind webview_find_in_page / webview_stop_find WebviewFindInPage / WebviewStopFind
view.openDevTools / closeDevTools / toggleDevTools openWebviewDevTools / closeWebviewDevTools / toggleWebviewDevTools open_webview_devtools / close_webview_devtools / toggle_webview_devtools OpenWebviewDevtools / CloseWebviewDevtools / ToggleWebviewDevtools
view.setPageZoom / getPageZoom setWebviewPageZoom / getWebviewPageZoom set_webview_page_zoom / get_webview_page_zoom SetWebviewPageZoom / GetWebviewPageZoom
view.executeJavascript(js) evaluateJavaScriptWithNoCompletion(id, js) evaluate_javascript_with_no_completion(id, js) EvaluateJavaScriptWithNoCompletion(id, js)
view.remove() removeWebview(id) remove_webview(id) RemoveWebview(id)
— (no TS history methods) canWebviewGoBack / canWebviewGoForward, webviewGoBack / webviewGoForward, reloadWebview can_webview_go_back / can_webview_go_forward, webview_go_back / webview_go_forward, reload_webview CanWebviewGoBack / CanWebviewGoForward, WebviewGoBack / WebviewGoForward, ReloadWebview

Not available natively: the typed RPC layer (defineRPC) — the native SDKs provide only the raw JSON bridge primitives, and apps implement the request/response envelope themselves; the .on() event emitter — native webview events arrive through the C callbacks fixed at creation (decide_navigation, event, and the bridge handlers); JavaScript evaluation with a returned result — only the fire-and-forget evaluateJavaScriptWithNoCompletion exists; and the download event stream (download-started through download-failed), which has no native equivalent.