Local Webview Assets
Electrobun maps files under the packaged Resources/app/views directory to the
views:// protocol. Use these URLs anywhere a webview accepts a normal URL.
Configure a view
Section titled “Configure a view”build.views bundles JavaScript or TypeScript entrypoints. build.copy copies
HTML, CSS, images, and other static files without transforming them.
import type { ElectrobunConfig } from "electrobun";
export default { app: { name: "Assets Example", identifier: "dev.example.assets", version: "1.0.0", }, build: { views: { mainview: { entrypoint: "src/mainview/index.ts", }, }, copy: { "src/mainview/index.html": "views/mainview/index.html", "src/mainview/style.css": "views/mainview/style.css", "src/mainview/logo.png": "views/mainview/logo.png", }, },} satisfies ElectrobunConfig;The destination views/mainview/index.html becomes
views://mainview/index.html at runtime. View names are application-defined;
you can add as many entries as needed.
Load bundled content
Section titled “Load bundled content”import { BrowserWindow } from "electrobun/main";
const mainWindow = new BrowserWindow({ title: "Bundled content", url: "views://mainview/index.html", frame: { width: 800, height: 600 },});
void mainWindow;BrowserWindow takes the URL in its constructor. Loading a new URL later is a
BrowserView operation: mainWindow.webview.loadURL(url).
Reference assets from HTML and CSS
Section titled “Reference assets from HTML and CSS”<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <title>Bundled content</title> <link rel="stylesheet" href="views://mainview/style.css" /> <script type="module" src="views://mainview/index.js"></script> </head> <body> <img src="views://mainview/logo.png" alt="Application logo" /> </body></html>body { background-image: url("views://mainview/logo.png");}Each configured view is emitted as views/<view-name>/index.js, independent of
the entrypoint’s filename. In this example, the mainview entry becomes
views/mainview/index.js.
Load mutable files with appdata://
Section titled “Load mutable files with appdata://”appdata:// maps to the app’s fixed, writable userData directory. Its exact
OS-specific location is available as Utils.paths.userData in TypeScript and
the userData / user_data / UserData field of the native SDKs’ resolved
paths. See Paths for the directory layout.
Access is granted per webview and is disabled by default. Enable it when
creating the BrowserWindow or BrowserView that needs to read those files:
import { BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({ url: "views://mainview/index.html", allowedProtocols: { appData: true, },});import { BrowserWindow } from "electrobun/main";
const win = new BrowserWindow({ url: "views://mainview/index.html", allowedProtocols: { appData: true, },});var webview_options = electrobun.WebviewOptions{ .window_id = window_id, .url = "views://mainview/index.html", .allowed_protocols = .{ .app_data = true },};const webview_id = try core.createWebview(webview_options);let mut webview_options = WebviewOptions::new( window_id, "views://mainview/index.html", Rect::new(0.0, 0.0, 800.0, 600.0),);webview_options.allowed_protocols = AllowedProtocols { views: true, app_data: true,};let webview_id = core.create_webview(webview_options)?;webviewOptions := electrobun.NewWebviewOptions( windowID, "views://mainview/index.html", electrobun.NewRect(0, 0, 800, 600),)webviewOptions.AllowedProtocols.AppData = truewebviewID, err := core.CreateWebview(webviewOptions)webview_options := electrobun.defaultWebviewOptions(window_id)webview_options.url = "views://mainview/index.html"webview_options.allowed_protocols.app_data = truewebview_id, webview_err := electrobun.createWebview(core, webview_options)Files written beneath userData are then available to that webview as normal
web resources:
<img src="appdata://images/avatar.png" alt="User avatar" />const response = await fetch("appdata://documents/report.txt");if (!response.ok) throw new Error("Could not load report");const report = await response.text();The protocol works from both views:// pages and remote pages, and its
responses are CORS-enabled. Permission follows the webview, not the current
page’s origin: if an enabled webview navigates to a remote URL, that remote
page can also request appdata:// files.
Both views:// and appdata:// are confined to their respective roots.
Absolute paths, .. traversal (including encoded traversal), and symlink
escapes outside the root are rejected.
Protocol defaults
Section titled “Protocol defaults”The complete per-webview option is:
type AllowedProtocols = { views?: boolean; // defaults to true appData?: boolean; // defaults to false};Set views: false for a webview that should not be able to read packaged UI
assets. Unspecified properties retain their defaults.