1- # WebUI Zig (Manual Port)
1+ # WebUI Zig
22
3- A Zig-first WebUI runtime with typed RPC, generated JS/TS bridge code, native-webview-first execution, and browser fallback .
3+ Zig-first WebUI runtime: native webview when available, browser fallback when needed, and a comptime-generated RPC bridge that feels like calling local functions from JS .
44
5- ## Status
5+ - Zig: ` 0.15.2+ ` (` build.zig.zon ` sets ` .minimum_zig_version ` )
6+ - CI: Linux/macOS/Windows via ` .github/workflows/ci.yml `
67
7- This project is actively usable, but it is not yet full behavioral parity with upstream ` webui.c ` .
8+ ## Status (Parity Snapshot)
89
9- Current parity snapshot (` zig build parity-local ` ):
10+ This repo targets ** behavioral parity with upstream ` webui.c ` ** , but it is not yet 100% there.
11+
12+ Current snapshot (` zig build parity-local ` ):
1013- ` total=40 `
1114- ` implemented=36 `
1215- ` partial=4 `
1316- ` missing=0 `
1417
15- Current partial areas:
18+ Partial areas (still require manual GUI validation and/or runtime completion) :
1619- ` window.visual.transparency `
1720- ` window.visual.frameless `
1821- ` window.visual.corner_radius `
1922- ` server.tls_toggle `
2023
21- See ` parity/status.json ` and ` docs/upstream_file_parity.md ` for details .
24+ See ` parity/status.json ` , ` docs/manual_gui_checklist.md ` , and ` docs/upstream_file_parity.md ` .
2225
23- ## Highlights
26+ ## What You Get
2427
25- - Zig-only active runtime/library build path (` @cImport ` and runtime C/C++/ObjC compilation removed).
26- - Idiomatic API (` App ` , ` Window ` , ` Service ` , ` RpcRegistry ` , ` WindowStyle ` , typed events).
27- - Comptime RPC registration via ` pub const rpc_methods = struct { ... } ` .
28- - Generated JS client + TypeScript declarations.
29- - ` sync ` , ` threaded ` , and ` custom ` RPC dispatch modes.
30- - Native-webview-first runtime with browser fallback.
31- - Extensive third-party browser discovery/search paths across Linux/macOS/Windows.
28+ - ** Pure Zig active build graph** : no ` @cImport ` , no ` translate-c ` , no runtime C/C++/ObjC compilation in the active library.
29+ - ** Dev-friendly API** : ` App ` , ` Window ` , ` Service ` , ` WindowStyle ` , ` WindowControl ` , typed ` Event ` s.
30+ - ** Comptime RPC surface** : define ` pub const rpc_methods = struct { ... } ` once, generate JS/TS bridge from it.
31+ - ** Push transport for scripts** : WebSocket push channel (no constant ` /lifecycle ` polling).
32+ - ** Aggressive browser discovery** : broad catalog + OS-specific search paths + env overrides.
33+ - ** Parity/test gates** : ` zig build test ` , ` zig build examples ` , ` zig build parity-local ` , ` zig build os-matrix ` .
3234
3335## Quick Start
3436
@@ -39,89 +41,75 @@ zig build examples
3941zig build run
4042```
4143
42- Run one example:
44+ Run a specific example:
4345
4446``` bash
45- zig build run -Dexample=translucent_rounded
47+ zig build run -Dexample=fancy_window
4648```
4749
48- Force runtime mode:
50+ Force runtime mode for examples :
4951
5052``` bash
5153zig build run -Dexample=fancy_window -Drun-mode=webview
5254zig build run -Dexample=fancy_window -Drun-mode=browser
5355```
5456
55- List all build steps/ options:
57+ List steps and options:
5658
5759``` bash
5860zig build -l
5961zig build -h
6062```
6163
62- ## Build Flags
64+ ## Add To Your Project
6365
64- | Flag | Default | Effect |
65- | ---| ---:| ---|
66- | ` -Ddynamic=true ` | ` false ` | Build/install ` webui ` as a shared library (` .so ` /` .dylib ` /` .dll ` ) instead of static archive. |
67- | ` -Denable-tls=true ` | ` false ` | Enables TLS defaults in runtime options/API state. |
68- | ` -Denable-webui-log=true ` | ` false ` | Enables runtime log defaults. |
69- | ` -Dminify-embedded-js=true ` | ` true ` | Minifies embedded runtime helper JS asset at build time. |
70- | ` -Dminify-written-js=true ` | ` false ` | Minifies written runtime helper JS output artifact. |
71- | ` -Dexample=<name> ` | ` all ` | Selects example used by ` zig build run ` . |
72- | `-Drun-mode=webview| browser` | ` webview ` | Chooses native-webview path or browser-mode path in examples. |
73- | ` -Dtarget=<triple> ` | host | Cross-compiles the library/examples for another target. |
66+ This is a normal Zig package (` .name = "webui" ` in ` build.zig.zon ` ).
7467
75- Exported compile-time values:
76- - ` webui.BuildFlags.dynamic `
77- - ` webui.BuildFlags.enable_tls `
78- - ` webui.BuildFlags.enable_webui_log `
79- - ` webui.BuildFlags.run_mode `
68+ ``` bash
69+ zig fetch --save < git-or-tarball-url>
70+ ```
8071
81- ## Build Steps
72+ ``` zig
73+ // build.zig
74+ const webui_dep = b.dependency("webui", .{
75+ .target = target,
76+ .optimize = optimize,
77+ });
78+ const webui = webui_dep.module("webui");
79+
80+ exe.root_module.addImport("webui", webui);
81+ ```
8282
83- - ` zig build ` (default install)
84- - ` zig build test `
85- - ` zig build examples `
86- - ` zig build run `
87- - ` zig build bridge `
88- - ` zig build runtime-helpers `
89- - ` zig build vfs-gen `
90- - ` zig build parity-report `
91- - ` zig build parity-local `
92- - ` zig build os-matrix `
83+ ## Transport Model
9384
94- ## API Overview
85+ Browser fallback serves local HTTP and uses a WebSocket push channel for script tasks and lifecycle signaling. Native mode uses the platform webview backend when available.
86+
87+ ``` mermaid
88+ flowchart LR
89+ A["Zig app (Service/App)"] --> B["Local HTTP server (browser fallback)"]
90+ B --> C["Browser tab/window"]
91+ C -->|WS push| D["/webui/ws"]
92+ C -->|HTTP RPC| E["/webui/rpc"]
93+ A --> F["Native webview backend"]
94+ F --> G["WebView window (OS)"]
95+ ```
9596
96- Top-level exports (` src/root.zig ` ):
97- - ` App ` , ` Window ` , ` Service `
98- - ` Event ` , ` EventKind `
99- - ` RpcRegistry ` , ` RpcOptions ` , ` DispatcherMode `
100- - ` WindowStyle ` , ` WindowControl ` , ` WindowCapability `
101- - ` BridgeOptions ` , ` TransportMode `
102- - ` ScriptOptions ` , ` ScriptEvalResult `
103- - ` TlsOptions ` , ` TlsInfo `
97+ ## API At A Glance
10498
10599Core flow:
106- 1 . Declare ` pub const rpc_methods ` as a comptime struct of functions.
107- 2 . Initialize ` Service ` or ` App + Window ` .
108- 3 . Show ` html ` , ` file ` , or ` url ` content.
109- 4 . Run app loop and exchange RPC/raw messages.
100+ 1 . Declare ` pub const rpc_methods = struct { ... } ` (comptime).
101+ 2 . Initialize ` Service ` (or ` App + Window ` ).
102+ 3 . ` showHtml/showFile/showUrl ` and ` run ` .
110103
111- ### Minimal Service Example
104+ Minimal service:
112105
113106``` zig
114107const std = @import("std");
115108const webui = @import("webui");
116109
117110pub const rpc_methods = struct {
118- pub fn ping() []const u8 {
119- return "pong";
120- }
121-
122- pub fn add(a: i64, b: i64) i64 {
123- return a + b;
124- }
111+ pub fn ping() []const u8 { return "pong"; }
112+ pub fn add(a: i64, b: i64) i64 { return a + b; }
125113};
126114
127115pub fn main() !void {
@@ -134,7 +122,7 @@ pub fn main() !void {
134122 .browser_fallback_on_native_failure = true,
135123 .auto_open_browser = true,
136124 },
137- .window = .{ .title = "WebUI Zig Demo " },
125+ .window = .{ .title = "WebUI Zig" },
138126 .rpc = .{ .dispatcher_mode = .threaded },
139127 });
140128 defer service.deinit();
@@ -145,17 +133,22 @@ pub fn main() !void {
145133 "<script type=\"module\" src=\"/webui_bridge.js\"></script></head>" ++
146134 "<body><button id=\"b\">Ping</button><pre id=\"out\"></pre>" ++
147135 "<script>document.getElementById('b').onclick=async()=>{" ++
148- "const p=await webuiRpc.ping();const s=await webuiRpc.add(20,22);" ++
149- "document.getElementById('out').textContent=`${p} ${s}`;};</script></body></html>",
136+ "document.getElementById('out').textContent=" ++
137+ "`ping=${await webuiRpc.ping()} add=${await webuiRpc.add(20,22)}`;};</script>" ++
138+ "</body></html>",
150139 });
151140
152141 try service.run();
142+ while (!service.shouldExit()) {
143+ std.Thread.sleep(10 * std.time.ns_per_ms);
144+ try service.run();
145+ }
153146}
154147```
155148
156149## Typed RPC + Bridge Generation
157150
158- All RPC methods are declared once at comptime :
151+ Everything starts with a comptime method set :
159152
160153``` zig
161154pub const rpc_methods = struct {
@@ -164,39 +157,92 @@ pub const rpc_methods = struct {
164157};
165158```
166159
167- Then you can:
168- - Serve runtime-generated client script: ` service.rpcClientScript(.{}) `
169- - Generate compile-time client script: ` webui.Service.generatedClientScriptComptime(rpc_methods, .{}) `
170- - Generate compile-time TypeScript declarations: ` webui.Service.generatedTypeScriptDeclarationsComptime(rpc_methods, .{}) `
160+ What you can generate:
161+ - Runtime-generated JS client string: ` Window.rpcClientScript(.{}) `
162+ - Comptime JS client string: ` webui.Service.generatedClientScriptComptime(rpc_methods, .{}) `
163+ - Comptime TypeScript declarations: ` webui.Service.generatedTypeScriptDeclarationsComptime(rpc_methods, .{}) `
164+
165+ Dispatch modes:
166+ - ` sync ` (direct execution)
167+ - ` threaded ` (worker queue)
168+ - ` custom ` (hook dispatcher)
169+
170+ ## Close Semantics (No Random Window Closes)
171171
172- Script execution APIs :
173- - ` Window.runScript(script, options) `
174- - ` Window.evalScript(allocator, script, options) `
172+ Close is backend-authoritative :
173+ - The frontend closes ** only ** after receiving a backend ` backend_close ` push signal.
174+ - The backend sends the close signal and waits briefly for ` close_ack ` before tearing down.
175175
176- ## Browser Support (Discovery Catalog)
176+ This is implemented in ` src/root.zig ` and ` src/bridge/runtime_helpers.source.js ` .
177177
178- The discovery catalog includes at least these families:
178+ ## Browser Discovery Catalog
179+
180+ The discovery catalog includes at least these families (and more):
179181- Firefox, Chrome, Edge, Chromium, Yandex, Brave, Vivaldi
180182- Epic, Safari, Opera
181- - Plus: Arc, DuckDuckGo, Tor, LibreWolf, Mullvad, Sidekick, Shift, Opera GX, Pale Moon, SigmaOS, Lightpanda
183+ - Arc, DuckDuckGo, Tor, LibreWolf, Mullvad, Sidekick, Shift, Opera GX, Pale Moon, SigmaOS, Lightpanda
182184
183- Notes :
184- - Discovery means executable/ path support in the catalog and search paths.
185- - Actual availability still depends on what is installable on each OS.
186- - Env overrides are supported: ` WEBUI_BROWSER_PATH ` , ` WEBUI_BROWSER ` , ` BROWSER ` .
185+ Overrides :
186+ - ` WEBUI_BROWSER_PATH ` (absolute path)
187+ - ` WEBUI_BROWSER ` (kind/name)
188+ - ` BROWSER ` (kind/name)
187189
188190## Runtime Helper JS Assets
189191
190- Runtime helper JS is maintained as a source file and exposed in two variants:
191- - ` webui.runtime_helpers_js ` (embedded variant )
192- - ` webui.runtime_helpers_js_written ` (written-file variant )
192+ Runtime helpers live in ` src/bridge/runtime_helpers. source.js ` and are built into two variants:
193+ - ` webui.runtime_helpers_js ` (embedded; minified by default )
194+ - ` webui.runtime_helpers_js_written ` (written-file; not minified by default )
193195
194196Build outputs:
195197- ` zig-out/share/webui/runtime_helpers.embed.js `
196198- ` zig-out/share/webui/runtime_helpers.written.js `
197199
200+ ## Build Flags
201+
202+ | Flag | Default | What it does |
203+ | ---| ---:| ---|
204+ | ` -Ddynamic=true ` | ` false ` | Builds/installs ` webui ` as a shared library (` .so ` /` .dylib ` /` .dll ` ) instead of a static archive. |
205+ | ` -Denable-tls=true ` | ` false ` | Enables TLS defaults in runtime options/API state (transport completion still tracked as partial). |
206+ | ` -Denable-webui-log=true ` | ` false ` | Enables runtime logging defaults (prints RPC/control/lifecycle diagnostics). |
207+ | ` -Dminify-embedded-js=true ` | ` true ` | Minifies the embedded runtime helper JS asset at build time. |
208+ | ` -Dminify-written-js=true ` | ` false ` | Minifies the written runtime helper JS output artifact. |
209+ | ` -Dexample=<name> ` | ` all ` | Selects which demo ` zig build run ` executes. |
210+ | `-Drun-mode=webview| browser` | ` webview ` | Chooses native-webview vs browser-mode path in examples. |
211+ | ` -Dtarget=<triple> ` | host | Cross-compiles the library/examples for another target. |
212+
213+ Exported compile-time values:
214+ - ` webui.BuildFlags.dynamic `
215+ - ` webui.BuildFlags.enable_tls `
216+ - ` webui.BuildFlags.enable_webui_log `
217+ - ` webui.BuildFlags.run_mode `
218+
219+ ## Useful Build Steps
220+
221+ - ` zig build ` (install)
222+ - ` zig build test `
223+ - ` zig build examples `
224+ - ` zig build run `
225+ - ` zig build bridge `
226+ - ` zig build runtime-helpers `
227+ - ` zig build vfs-gen `
228+ - ` zig build parity-report `
229+ - ` zig build parity-local `
230+ - ` zig build os-matrix `
231+
198232## Examples
199233
234+ Run all demos:
235+
236+ ``` bash
237+ zig build run
238+ ```
239+
240+ Run one demo:
241+
242+ ``` bash
243+ zig build run -Dexample=translucent_rounded -Drun-mode=webview
244+ ```
245+
200246Available ` -Dexample= ` values:
201247- ` minimal `
202248- ` call_js_from_zig `
@@ -217,30 +263,31 @@ Available `-Dexample=` values:
217263- ` call_oop_from_js `
218264- ` serve_folder_oop `
219265- ` vfs_oop `
220- - ` all ` (default for ` zig build run ` )
266+ - ` all `
221267
222268## Production Notes
223269
224- What is strong now:
225- - Typed RPC and generated bridge tooling.
226- - Browser discovery breadth and fallback policy controls.
227- - Build/test/parity automation (` parity-local ` , ` os-matrix ` , static guards).
270+ Strong now:
271+ - Typed RPC + generated bridge tooling.
272+ - Browser discovery breadth and fallback control.
273+ - Push messaging for script execution (WebSocket).
274+ - Parity/test gates and static build guards.
228275
229- What still needs completion for strict full parity:
230- - TLS-enabled transport should be true HTTPS end- to-end (currently TLS state exists but transport path is still partial ).
231- - Visual parity for transparency/frameless/corner radius is still marked partial and relies on manual GUI validation .
276+ Still tracked as partial for strict upstream parity:
277+ - End- to-end HTTPS transport ( ` server.tls_toggle ` ).
278+ - Visual parity items require manual GUI smoke on real desktops .
232279
233- Use ` docs/manual_gui_checklist.md ` for required Linux/macOS/Windows smoke validation .
280+ Manual GUI validation checklist: ` docs/manual_gui_checklist.md ` .
234281
235- ## Repository Layout
282+ ## Layout
236283
237- - ` src/ ` - active Zig runtime and API.
238- - ` tools/ ` - build-time generators (` bridge_gen.zig ` , ` vfs_gen.zig ` , asset tooling).
239- - ` webui/examples/ ` - Zig example entrypoints and example assets.
240- - ` docs /` - parity and manual validation docs.
241- - ` parity /` - parity status + report definitions.
284+ - ` src/ ` - active Zig runtime + public API ( ` src/root.zig ` )
285+ - ` tools/ ` - build-time generators (bridge/VFS/assets)
286+ - ` docs/ ` - parity audit + manual validation checklists
287+ - ` parity /` - parity status + report definitions
288+ - ` upstream_snapshot /` - archived upstream sources (not in active builds)
242289
243- ## Migration Docs
290+ ## Docs
244291
245292- ` MIGRATION.md `
246293- ` CHANGELOG.md `
0 commit comments