← back

Lightweight Native Webviews for Bun, Deno & Node.js

1 min read

While building Elgato Stream Deck plugins, I kept needing to open native windows from key presses — for richer interaction beyond the small key UI. There’s no built-in way to do this without Electron or signed external webview runtimes (see comparison).

So I built native-window — a library that creates native OS windows with embedded web content directly from Bun, Deno & Node.js. It uses wry and tao (the libraries behind Tauri) for cross-platform support.

What it is

native-window is a Rust napi-rs addon using platform-native webview engines — WebKit on macOS and Linux, WebView2 on Windows. No bundled Chromium.

import { NativeWindow } from "@nativewindow/webview";

const win = new NativeWindow({
  title: "My App",
  width: 800,
  height: 600,
});

win.loadUrl("https://example.com");

win.onClose(() => {
  process.exit(0);
});

Key highlights

  • Cross-platform — native webview engines, no bundled browser
  • Typed IPC — schema-first messaging with compile-time type checking via Zod, Valibot, or any safeParse()-compatible library
  • React hooksuseChannelEvent, useSend, and ChannelProvider for idiomatic React integration
  • TanStack DB adapter — sync host-side data to reactive TanStack DB collections
  • Security built-in — URL scheme blocking, CSP, trusted origin filtering, IPC bridge hardening, message size limits, schema validation

Typed IPC in action

import { z } from "zod";
import { createWindow } from "@nativewindow/ipc";

const ch = createWindow(
  { title: "My App", width: 800, height: 600 },
  {
    schemas: {
      host: {
        "update-title": z.string(),
      },
      client: {
        "user-click": z.object({ x: z.number(), y: z.number() }),
      },
    },
  },
);

ch.send("update-title", "Hello!");
ch.on("user-click", (pos) => {
  console.log(`Click at ${pos.x}, ${pos.y}`);
});

Packages

PackageDescription
@nativewindow/webviewRust napi-rs addon providing native window + webview APIs
@nativewindow/ipcPure TypeScript typesafe IPC channel layer
@nativewindow/reactReact bindings for the typed IPC layer
@nativewindow/tsdbTanStack DB collection adapter for native-window IPC

Get started

bun add @nativewindow/webview

Full documentation at nativewindow.fcannizzaro.com.