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.

Constructor options

The constructor accepts Partial<BrowserViewOptions>.

OptionTypeDefaultPurpose
windowIdnumber0Native parent window ID.
hostWebviewIdnumbernoneHost view for an <electrobun-webview> child.
urlstring | nullnullURL to load.
htmlstring | nullnullHTML string to load instead of url.
preloadstring | nullnullInline JavaScript or a bundled views:// script URL.
viewsRootstring | nullnullOverride for the bundled views root.
renderer"native" | "cef"Platform build defaultWebview renderer.
partitionstring | nullnullPersistent 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.
autoResizebooleantrueResize with the parent window.
rpcRPC instancegenerated empty RPCTyped main-process transport.
navigationRulesstring | nullnullSerialized navigation policy.
sandboxbooleanfalseDisable RPC for untrusted content.
startTransparentbooleanfalseCreate the native layer transparent.
startPassthroughbooleanfalseCreate with input passthrough enabled.
spellCheckbooleanfalseEnable native spell checking where supported.

Loading and scripting

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.

Find in page

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();

Events

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.

Typed RPC

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.

Lookup, adoption, and removal

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.

Public methods

  • 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.

Native SDKs

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:

TypeScriptZig / OdinRustGo
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 optionresizeWebview(id, frame, masks_json)resize_webview(id, frame, masks_json)ResizeWebview(id, frame, masksJSON)
startTransparent / startPassthrough optionssetWebviewTransparent / setWebviewPassthrough / setWebviewHiddenset_webview_transparent / set_webview_passthrough / set_webview_hiddenSetWebviewTransparent / 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 / stopFindInPagewebviewFindInPage / webviewStopFindwebview_find_in_page / webview_stop_findWebviewFindInPage / WebviewStopFind
view.openDevTools / closeDevTools / toggleDevToolsopenWebviewDevTools / closeWebviewDevTools / toggleWebviewDevToolsopen_webview_devtools / close_webview_devtools / toggle_webview_devtoolsOpenWebviewDevtools / CloseWebviewDevtools / ToggleWebviewDevtools
view.setPageZoom / getPageZoomsetWebviewPageZoom / getWebviewPageZoomset_webview_page_zoom / get_webview_page_zoomSetWebviewPageZoom / 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, reloadWebviewcan_webview_go_back / can_webview_go_forward, webview_go_back / webview_go_forward, reload_webviewCanWebviewGoBack / 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.