zig-webview
March 29, 2026 · View on GitHub
Zig bindings for webview/webview — a tiny cross-platform library for building desktop applications with web technologies using a native browser widget.
Also includes cross-platform window control such as maximize, minimize, fullscreen, hide/show and state queries.
Idiomatic Zig API featuring error unions and comptime-powered typed callbacks.
Requirements
Minimum Zig version: 0.15.2.
For platform-specific requirements (WebKitGTK, WebView2, etc.), refer to the webview/webview documentation.
Installation
Run the following command in your project directory to add the dependency:
zig fetch --save=webview git+https://github.com/happystraw/zig-webview
Then import the module in build.zig:
const webview_dep = b.dependency("webview", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("webview", webview_dep.module("webview"));
Quick Start
const Webview = @import("webview").Webview;
pub fn main() !void {
const w = try Webview.create(false, null);
defer w.destroy() catch unreachable;
try w.setTitle("Hello");
try w.setSize(800, 600, .none);
try w.setHtml("Thanks for using webview!");
try w.run();
}
Examples
| Example | Description |
|---|---|
| basic | Minimal window that loads an HTML string |
| bind | Counter and async compute demo using JS ↔ Zig bindings via bind / respond |
| easy | Counter demo using Easy wrapper with typed context and automatic error forwarding |
| window | Window state controls demo (maximize, minimize, fullscreen, hide/show) |
| skeleton | Project template with a Zig backend and a TypeScript frontend bundled by Bun |
Build and run the bundled examples with:
zig build examples
./zig-out/bin/basic
./zig-out/bin/bind
./zig-out/bin/easy
./zig-out/bin/window
Cross-compilation
Cross-compilation to macOS and Windows is supported.
Targeting macOS
Obtain a macOS SDK (e.g. via macosx-sdks) and pass its path with -Dmacos-sdk:
zig build examples -Dtarget=aarch64-macos -Dmacos-sdk=/path/to/MacOSX.sdk
# or for x86_64
zig build examples -Dtarget=x86_64-macos -Dmacos-sdk=/path/to/MacOSX.sdk
Targeting Windows
The required WebView2 headers are already bundled in deps/WebView2/, so no extra setup is needed:
zig build examples -Dtarget=x86_64-windows
Easy API
Webview.Easy(T) pairs a *Webview with a typed context *T and enhances bind to accept methods of T. Errors returned from bound methods are automatically forwarded to JS via reject.
const std = @import("std");
const Webview = @import("webview").Webview;
const Easy = Webview.Easy(Context);
const Context = struct {
num: i64,
pub fn increment(self: *Context, req: Easy.Request) !void {
self.num += 1;
var buf: [32]u8 = undefined;
req.resolveWith(try std.fmt.bufPrintZ(&buf, "{d}", .{self.num}));
}
};
pub fn main() !void {
var ctx: Context = .{ .num = 0 };
var easy: Easy = try .init(&ctx, .debug); // or .release
defer easy.deinit();
try easy.bind(.increment);
try easy.setTitle("Easy Example");
try easy.setSize(480, 320, .none);
try easy.setHtml("<button onclick=\"increment().then(n => this.textContent='Clicked ' + n + ' times')\">Click me</button>");
try easy.run();
}
Options:
.release(DevTools off).debug(DevTools on)- Custom handle:
.{ .devtools = true, .window = ptr }
Request — settle the JS Promise from a bound method:
| Method | Result |
|---|---|
req.resolve() | Fulfill with undefined |
req.resolveWith(json) | Fulfill with a JSON value |
req.reject(json) | Reject with a JSON value |
req.rejectError(err) | Reject with an error name |
req.args is a raw JSON array, e.g. "[1, \"hello\"]".
Binding — Easy forwards all Webview methods, with three binding variants:
| Method | Description |
|---|---|
easy.bind(.method) | Bind a method of T by declaration name |
easy.bindAs(name, .method) | Bind a method of T under a custom JS name |
easy.bindFn(name, fn) | Bind an arbitrary fn(Easy.Request) void |
API Reference
C API to Zig API Mapping
| C Function | Zig Method |
|---|---|
webview_create(debug, window) | Webview.create(devtools, window) !*Webview |
webview_destroy(w) | w.destroy() !void |
webview_run(w) | w.run() !void |
webview_terminate(w) | w.terminate() !void |
webview_dispatch(w, fn, arg) | w.dispatchRaw(callback, arg) !void |
webview_dispatch(w, fn, arg) | w.dispatch(T, callback, arg) !void |
webview_dispatch(w, fn, null) | w.dispatchSimple(callback) !void |
webview_get_window(w) | w.getWindow() ?*anyopaque |
webview_get_native_handle(w, kind) | w.getNativeHandle(kind) ?*anyopaque |
webview_set_title(w, title) | w.setTitle(title) !void |
webview_set_size(w, width, height, hint) | w.setSize(width, height, hint) !void |
webview_navigate(w, url) | w.navigate(url) !void |
webview_set_html(w, html) | w.setHtml(html) !void |
webview_init(w, js) | w.addInitScript(js) !void |
webview_eval(w, js) | w.eval(js) !void |
webview_bind(w, name, fn, arg) | w.bindRaw(name, callback, arg) !void |
webview_bind(w, name, fn, arg) | w.bind(T, name, callback, arg) !void |
webview_bind(w, name, fn, null) | w.bindSimple(name, callback) !void |
webview_unbind(w, name) | w.unbind(name) !void |
webview_return(w, id, status, result) | w.respond(id, status, result) !void |
webview_version() | Webview.version() Version |
Window Control Methods
These methods are extensions beyond the upstream webview/webview C API and are implemented directly in this library on top of each platform's native window handle.
| Method | Description |
|---|---|
w.maximize() !void | Maximize the window |
w.unmaximize() !void | Restore the window from maximized state |
w.minimize() !void | Minimize the window |
w.unminimize() !void | Restore the window from minimized state |
w.fullscreen() !void | Enter fullscreen mode |
w.unfullscreen() !void | Exit fullscreen mode |
w.hide() !void | Hide the window |
w.show() !void | Show the window |
w.isMaximized() !bool | Query whether the window is maximized |
w.isMinimized() !bool | Query whether the window is minimized |
w.isFullscreen() !bool | Query whether the window is in fullscreen mode |
w.isVisible() !bool | Query whether the window is visible |