Use this file to discover all available pages before exploring further.
WebviewJS follows a straightforward three-object model: an Application owns the native event loop and all top-level resources; a BrowserWindow represents one OS window; and a Webview is the embedded browser engine rendered inside that window. Every meaningful desktop app you build with WebviewJS will start with these three primitives, wire up a handful of event listeners, and then call app.run() or app.whenReady() to hand control to the native GUI layer.
Keep a strong reference to the returned BrowserWindow handle (e.g. assign it to a module-level variable). If the reference is garbage-collected while the window is still open, method calls on the handle will throw a disposed error.
3
Create a Webview inside the window
win.createWebview() embeds a browser engine into the window. You can point it at a remote URL or supply inline HTML directly.
For apps that bundle their own UI, pass html instead of url. The string is set directly as the document source — no HTTP server required.
const webview = win.createWebview({ html: `<!DOCTYPE html><html> <head><title>Simple Example</title></head> <body> <h1>Hello, WebviewJS!</h1> <p>This is a simple example of a webview window.</p> </body></html>`,});
For larger applications consider using a Custom Protocol to serve files from disk, or a bundler output directory — this keeps your Node entry file clean and lets the webview load assets normally via <script> and <link> tags.
Application is a typed EventEmitter. Subscribe to lifecycle events before calling app.run() so no events are missed.
// Fired when any window's close button is clickedapp.on('window-close-requested', () => { console.log('A window was closed');});// Fired when the last window closes — the right place to call app.exit()app.on('application-close-requested', () => { console.log('All windows closed — exiting'); app.exit();});// Fired when a custom menu item (one with an id you assigned) is clickedapp.on('custom-menu-click', ({ customMenuEvent }) => { console.log('Menu item clicked:', customMenuEvent.id); if (customMenuEvent.id === 'quit') { app.exit(); }});
If you do not listen to application-close-requested and call app.exit() (or otherwise stop the process), the Node process may hang after the last window closes because the event-pump timer keeps running. Always handle this event in production apps.
Every object returned by a create* method — BrowserWindow, Webview, WebContext, TrayIcon — is a JavaScript wrapper around a native resource. The Application owns those native resources, but the JavaScript wrappers can be garbage-collected independently.Keep strong references in module-level or application-state variables for any handle whose methods or event listeners you still need:
// ❌ Risky — local variables may be GC'd; event listeners on webview become unreachableapp.whenReady().then(() => { const win = app.createBrowserWindow(); const webview = win.createWebview({ url: 'https://example.com' }); webview.onIpcMessage(() => { /* ... */ }); // listener may be lost});
Once app.exit() is called, all wrapped resources are disposed. Calling methods on a disposed handle throws a disposed error; use handle.isDisposed() to guard if needed.
For structured, typed request/response style calls from the page into Node, use webview.expose(). Each exposed function returns a Promise in the browser.
All arguments and return values must be JSON-serializable. Passing non-serializable values (functions, undefined, circular references) throws a SerializationError.
You can also use a custom IPC alias name so the page uses window.bindings (while window.ipc still works):
const webview = win.createWebview({ html: '...', ipcName: 'bindings',});webview.onIpcMessage((msg) => console.log(msg.body.toString()));// Page can use either: window.bindings.postMessage('hello')// or: window.ipc.postMessage('hello')
WebviewJS supports the TC39 Explicit Resource Management proposal. Wrap an Application (or any handle) in a using declaration and its dispose() method is called automatically when the block exits — even on exception.
{ using app = new Application(); const win = app.createBrowserWindow({ title: 'Disposable', width: 800, height: 600 }); const webview = win.createWebview({ html: '<h1>Auto-cleaned up</h1>' }); app.run();} // app.exit() called automatically here
Individual BrowserWindow, Webview, WebContext, and TrayIcon objects also support dispose() and [Symbol.dispose]() for fine-grained early cleanup without tearing down the entire application:
// Close a single window early and release its resourceswin[Symbol.dispose]();
Symbol.dispose and the using declaration are part of the TC39 Explicit Resource Management proposal. They are fully supported under the Node.js >= 24 baseline that WebviewJS requires.