@webviewjs/webview) is a native binding to tao and wry — the same battle-tested Rust GUI primitives that power Tauri — exposed directly to Node.js, Deno, and Bun through a zero-overhead NAPI-RS bridge. You get real OS windows, a system webview, menus, tray icons, IPC, custom protocols, and desktop notifications without shipping a bundled browser or adopting a full application framework.
Quickstart
Create your first native window in under five minutes.
IPC Messaging
Send messages between the page and Node.js in both directions.
API Reference
Full reference for Application, BrowserWindow, Webview, and more.
Build Executables
Compile your app into a single self-contained binary.
What you can build
WebviewJS gives you direct access to OS-level GUI primitives from JavaScript:- Desktop windows — create, resize, move, and style native OS windows with full decoration control
- Embedded webviews — render any URL or inline HTML inside a native window using the OS’s own WebKit/WebView2 engine
- Promise-based readiness —
app.whenReady()resolves after the first nativeResumedevent, giving you a clean async entry point for window creation - Non-blocking event pump —
app.run()drives the GUI viasetIntervalso all of Node’s async I/O, timers, and network continue to work normally alongside the GUI - Bidirectional IPC — send typed messages from the page to Node via
window.ipc.postMessage()and call back withwebview.evaluateScript() - Exposed function namespaces — publish async Node.js functions to the page with
webview.expose(), callable asawait window.myNS.myFn() - Custom protocols — serve local files or handle
app://requests with a Fetch-compatible handler, including full Hono routing without an HTTP server - Native menus — build cross-platform menu bars with keyboard accelerators, roles, and per-window menus
- System tray icons — create tray icons with menus, tooltips, and pointer event listeners
- Desktop notifications — show native OS notifications with a browser-familiar API; permission is always
"granted"for native apps - Shared browser contexts — isolate cookies, caches, and storage across webviews using
WebContextprofiles - DevTools access — open or close the browser DevTools panel programmatically
- CLI build tool — the
webviewCLI compiles your app to a self-contained single-file executable targeting Node.js, Deno, or Bun
Supported runtimes
Prebuilt native binaries are published for every supported platform —
npm install downloads the correct binary automatically. No Rust toolchain is required for normal use.
Supported platforms
How it works
WebviewJS is a thin NAPI-RS binding. When your JavaScript callsapp.createBrowserWindow(), the call crosses the JS/Rust boundary synchronously and creates a native window handle owned by the Rust runtime. The webview is embedded inside that window using wry, which delegates to the OS’s own rendering engine — WebView2 on Windows, WebKit on macOS, and WebKitGTK on Linux.
The event loop bridges Node and the native GUI through a non-blocking pump_events() call that drains the OS message queue without blocking Node’s event loop. app.run() sets up a setInterval at ~16 ms (configurable) that calls pumpEvents() on each tick. Because this runs inside a normal Node timer, all of Node’s async I/O continues working exactly as usual alongside the GUI.
IPC crosses the JS/Rust boundary in the opposite direction: the page calls window.ipc.postMessage(), which routes through the native webview’s script-message bridge into your Node handler.
WebviewJS is a lightweight system webview binding, not a full application framework. It does not bundle a browser engine, provide a build system, or abstract away the OS the way Electron or Tauri do. You get direct, low-level access to native windowing and webview primitives from JavaScript — what you build on top of that is entirely up to you.