1- # WebUI Zig Manual Port
1+ # WebUI Zig ( Manual Port)
22
3- This repository now uses a Zig-only active runtime and build graph .
3+ A Zig-first WebUI runtime with typed RPC, generated JS/TS bridge code, native-webview-first execution, and browser fallback .
44
5- ## What changed
5+ ## Status
66
7- - No ` @cImport `
8- - No active C/C++/ObjC compilation in runtime/library build paths
9- - JS helper asset processing/minification is pure Zig (no ` zig cc ` path)
10- - Idiomatic Zig API surface:
11- - ` App `
12- - ` Window `
13- - ` Event `
14- - ` RpcRegistry `
15- - ` DispatcherMode `
16- - ` BridgeOptions `
17- - ` TransportMode `
7+ This project is actively usable, but it is not yet full behavioral parity with upstream ` webui.c ` .
188
19- Legacy native and script sources are archived in:
9+ Current parity snapshot (` zig build parity-local ` ):
10+ - ` total=40 `
11+ - ` implemented=36 `
12+ - ` partial=4 `
13+ - ` missing=0 `
2014
21- - ` upstream_snapshot/webui-2.5.0-beta.4/ `
15+ Current partial areas:
16+ - ` window.visual.transparency `
17+ - ` window.visual.frameless `
18+ - ` window.visual.corner_radius `
19+ - ` server.tls_toggle `
2220
23- ## Build
21+ See ` parity/status.json ` and ` docs/upstream_file_parity.md ` for details.
22+
23+ ## Highlights
24+
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.
32+
33+ ## Quick Start
2434
2535``` bash
2636zig build
2737zig build test
2838zig build examples
29- zig build parity-report
30- zig build parity-local
31- zig build os-matrix
32- zig build bridge
3339zig build run
34- zig build run -Dexample=fancy_window
3540```
3641
37- ` zig build run ` runs all examples by default ( ` -Dexample=all ` ) with a native-webview-first configuration and browser fallback enabled.
42+ Run one example:
3843
39- Available ` -Dexample= ` values:
40- - ` minimal `
41- - ` call_js_from_zig `
42- - ` call_zig_from_js `
43- - ` serve_folder `
44- - ` vfs `
45- - ` public_network `
46- - ` multi_client `
47- - ` chatgpt_api `
48- - ` custom_web_server `
49- - ` react `
50- - ` frameless `
51- - ` fancy_window `
52- - ` translucent_rounded `
53- - ` text_editor `
54- - ` minimal_oop `
55- - ` call_js_oop `
56- - ` call_oop_from_js `
57- - ` serve_folder_oop `
58- - ` vfs_oop `
59- - ` all ` (batch mode with short auto-timeout per example)
44+ ``` bash
45+ zig build run -Dexample=translucent_rounded
46+ ```
47+
48+ Force runtime mode:
6049
61- ` zig build os-matrix ` compiles the library and examples across Linux/macOS/Windows targets with static and dynamic linkage combinations.
50+ ``` bash
51+ zig build run -Dexample=fancy_window -Drun-mode=webview
52+ zig build run -Dexample=fancy_window -Drun-mode=browser
53+ ```
54+
55+ List all build steps/options:
56+
57+ ``` bash
58+ zig build -l
59+ zig build -h
60+ ```
6261
63- ### Build Flags
62+ ## Build Flags
6463
65- - ` -Ddynamic=true `
66- - Builds ` webui ` as a shared library (` .so ` /` .dylib ` /` .dll ` ) instead of a static archive.
67- - This changes artifact linkage format only; it does not enable/disable runtime features by itself.
68- - ` -Denable-tls=true `
69- - Sets TLS-enabled default at compile time for runtime options.
70- - ` -Denable-webui-log=true `
71- - Sets WebUI logging-enabled default at compile time for runtime options.
72- - ` -Dminify-embedded-js=true ` (default: ` true ` )
73- - Processes embedded runtime helper JS (used by runtime-generated bridge strings) using pure Zig tooling.
74- - ` -Dminify-written-js=true ` (default: ` false ` )
75- - Processes written runtime helper JS assets (used by file-writing bridge generation paths) using pure Zig tooling.
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. |
7674
77- These compile-time values are exported by the module as :
75+ Exported compile-time values:
7876- ` webui.BuildFlags.dynamic `
7977- ` webui.BuildFlags.enable_tls `
8078- ` webui.BuildFlags.enable_webui_log `
81-
82- ## Usage
79+ - ` webui.BuildFlags.run_mode `
80+
81+ ## Build Steps
82+
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 `
93+
94+ ## API Overview
95+
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 `
104+
105+ Core 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.
110+
111+ ### Minimal Service Example
83112
84113``` zig
85114const std = @import("std");
@@ -89,6 +118,10 @@ pub const rpc_methods = struct {
89118 pub fn ping() []const u8 {
90119 return "pong";
91120 }
121+
122+ pub fn add(a: i64, b: i64) i64 {
123+ return a + b;
124+ }
92125};
93126
94127pub fn main() !void {
@@ -101,101 +134,114 @@ pub fn main() !void {
101134 .browser_fallback_on_native_failure = true,
102135 .auto_open_browser = true,
103136 },
104- .window = .{
105- .title = "Demo",
106- .style = .{
107- .frameless = true,
108- .transparent = true,
109- .corner_radius = 12,
110- },
111- },
137+ .window = .{ .title = "WebUI Zig Demo" },
138+ .rpc = .{ .dispatcher_mode = .threaded },
112139 });
113140 defer service.deinit();
114141
115- const bridge_js = webui.Service.generatedClientScriptComptime(rpc_methods, .{});
116- const bridge_dts = webui.Service.generatedTypeScriptDeclarationsComptime(rpc_methods, .{});
117- _ = bridge_js;
118- _ = bridge_dts;
142+ try service.show(.{
143+ .html =
144+ "<!doctype html><html><head><meta charset=\"utf-8\"/>" ++
145+ "<script type=\"module\" src=\"/webui_bridge.js\"></script></head>" ++
146+ "<body><button id=\"b\">Ping</button><pre id=\"out\"></pre>" ++
147+ "<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>",
150+ });
119151
120- try service.show(.{ .html = "<html><body>Hello</body></html>" });
121152 try service.run();
122- _ = try service.control(.maximize);
123153}
124154```
125155
126- ## Notes
127-
128- - ` zig build bridge ` generates ` zig-out/share/webui/webui_bridge.js ` .
129- - ` zig build bridge ` also generates ` zig-out/share/webui/webui_bridge.d.ts ` .
130- - ` zig build runtime-helpers ` prepares helper assets:
131- - ` zig-out/share/webui/runtime_helpers.embed.js ` (default minified)
132- - ` zig-out/share/webui/runtime_helpers.written.js ` (default non-minified)
133- - Declare RPC methods in app entrypoints as ` pub const rpc_methods = struct { ... }; ` .
134- - The same ` rpc_methods ` constant should be used for:
135- - service initialization: ` webui.Service.init(allocator, rpc_methods, ...) `
136- - compile-time JS generation: ` webui.Service.generatedClientScriptComptime(rpc_methods, ...) `
137- - compile-time TS generation: ` webui.Service.generatedTypeScriptDeclarationsComptime(rpc_methods, ...) `
138- - The typed RPC bridge can also be emitted at runtime from ` Service.rpcClientScript() ` / ` RpcRegistry.generatedClientScript() ` .
139- - Runtime helper JS strings are exported as:
140- - ` webui.runtime_helpers_js ` (embedded/default variant)
141- - ` webui.runtime_helpers_js_written ` (written-file variant)
142- - Friendly shortcuts:
143- - ` App.initDefault(allocator) `
144- - ` App.window() ` / ` App.windowWithTitle(title) `
145- - ` Window.show(.{ .html = ... | .file = ... | .url = ... }) `
146- - ` Window.applyStyle(WindowStyle) `
147- - ` Window.currentStyle() `
148- - ` Window.lastWarning() ` / ` Window.clearWarning() `
149- - ` Window.control(WindowControl) `
150- - ` Window.setCloseHandler(handler, context) `
151- - ` Window.capabilities() `
152- - ` Window.bindRpc(RpcStruct, RpcOptions) `
153- - ` Window.rpcClientScript(BridgeOptions) `
154- - ` Window.rpcTypeDeclarations(BridgeOptions) `
155- - ` Service.init(allocator, rpc_methods, options) `
156- - ` Service.generatedClientScriptComptime(rpc_methods, options) `
157- - ` Service.generatedTypeScriptDeclarationsComptime(rpc_methods, options) `
158- - ` Service.lastWarning() ` / ` Service.clearWarning() `
159- - ` webui.process_signals.install() ` / ` webui.process_signals.stopRequested() ` for immediate ` Ctrl+C ` shutdown handling
160- - Comptime bridge generation is available via ` RpcRegistry.generatedClientScriptComptime(RpcStruct, options) ` .
161- - TypeScript declarations are available via:
162- - ` RpcRegistry.generatedTypeScriptDeclarations(options) `
163- - ` RpcRegistry.generatedTypeScriptDeclarationsComptime(RpcStruct, options) `
164- - ` RpcRegistry.writeGeneratedTypeScriptDeclarations(path, options) `
165- - Third-party browser-side JS libraries are preserved as static assets.
166- - Manual desktop smoke checklist: ` docs/manual_gui_checklist.md ` .
167-
168- ## Runtime Transport
169-
170- - Browser fallback runtime now serves:
171- - bridge script route (default ` /webui_bridge.js ` )
172- - RPC route (default ` /webui/rpc ` )
173- - local content (` showHtml ` / ` showFile ` ) over ` http://127.0.0.1:<port>/ `
174- - Browser control APIs:
175- - ` Window.browserUrl() ` returns the local browser-render URL.
176- - ` Window.openInBrowser() ` explicitly opens the window content in a discovered browser.
177- - ` Window.openInBrowserWithOptions(webui.BrowserLaunchOptions) ` overrides default browser launch policy per call.
178- - ` AppOptions.browser_launch.prompt_policy ` supports ` quiet_default ` and ` browser_default ` presets.
179- - Window parity routes (used by generated bridge helpers):
180- - ` POST /webui/window/control ` (` minimize|maximize|restore|close|hide|show ` )
181- - ` GET|POST /webui/window/style `
182- - If ` transport_mode = .native_webview ` , ` browser_fallback_on_native_failure=true ` (default) keeps browser rendering available.
183- - Window style/control calls are routed through backend abstractions first, then browser emulation when native behavior is unavailable.
184- - When a native backend cannot satisfy a requested style/control on the current target/runtime, WebUI emits warning events/logs, sets ` lastWarning() ` , and falls back to emulation when enabled.
185- - Browser fallback launch tracks spawned browser PID when available and terminates it on ` shutdown() ` .
186- - On POSIX, browser fallback is launched as a direct child process and assigned its own process group; shutdown kills the full browser process group.
187- - If PID tracking is unavailable on a platform/launcher path, frontend lifecycle heartbeat remains the fallback close mechanism.
188- - Browser catalog includes at least:
189- - Firefox, Chrome, Edge, Chromium, Yandex, Brave, Vivaldi (Windows/macOS/Linux)
190- - Epic (Windows/macOS/Linux catalog entry)
191- - Safari (Windows/macOS/Linux catalog entry; active availability varies by OS)
192- - Opera (Windows/macOS/Linux catalog entry)
193- - Dispatcher modes:
194- - ` sync ` : invoke RPC on request thread
195- - ` threaded ` : request thread submits RPC to worker thread queue (poll-driven condition waits)
196- - ` custom ` : user callback receives function name + invoker + parsed args
197- - Bridge/rpc routes and namespace are configurable via ` BridgeOptions ` .
198- - Network transport model:
199- - one listener thread accepts and handles HTTP requests
200- - threaded RPC dispatch hands off execution to a worker thread queue
201- - listener thread uses condition-variable polling waits for worker completion and then writes the response
156+ ## Typed RPC + Bridge Generation
157+
158+ All RPC methods are declared once at comptime:
159+
160+ ``` zig
161+ pub const rpc_methods = struct {
162+ pub fn ping() []const u8 { return "pong"; }
163+ pub fn add(a: i64, b: i64) i64 { return a + b; }
164+ };
165+ ```
166+
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, .{}) `
171+
172+ Script execution APIs:
173+ - ` Window.runScript(script, options) `
174+ - ` Window.evalScript(allocator, script, options) `
175+
176+ ## Browser Support (Discovery Catalog)
177+
178+ The discovery catalog includes at least these families:
179+ - Firefox, Chrome, Edge, Chromium, Yandex, Brave, Vivaldi
180+ - Epic, Safari, Opera
181+ - Plus: Arc, DuckDuckGo, Tor, LibreWolf, Mullvad, Sidekick, Shift, Opera GX, Pale Moon, SigmaOS, Lightpanda
182+
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 ` .
187+
188+ ## Runtime Helper JS Assets
189+
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)
193+
194+ Build outputs:
195+ - ` zig-out/share/webui/runtime_helpers.embed.js `
196+ - ` zig-out/share/webui/runtime_helpers.written.js `
197+
198+ ## Examples
199+
200+ Available ` -Dexample= ` values:
201+ - ` minimal `
202+ - ` call_js_from_zig `
203+ - ` call_zig_from_js `
204+ - ` serve_folder `
205+ - ` vfs `
206+ - ` public_network `
207+ - ` multi_client `
208+ - ` chatgpt_api `
209+ - ` custom_web_server `
210+ - ` react `
211+ - ` frameless `
212+ - ` fancy_window `
213+ - ` translucent_rounded `
214+ - ` text_editor `
215+ - ` minimal_oop `
216+ - ` call_js_oop `
217+ - ` call_oop_from_js `
218+ - ` serve_folder_oop `
219+ - ` vfs_oop `
220+ - ` all ` (default for ` zig build run ` )
221+
222+ ## Production Notes
223+
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).
228+
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.
232+
233+ Use ` docs/manual_gui_checklist.md ` for required Linux/macOS/Windows smoke validation.
234+
235+ ## Repository Layout
236+
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.
242+
243+ ## Migration Docs
244+
245+ - ` MIGRATION.md `
246+ - ` CHANGELOG.md `
247+ - ` docs/upstream_file_parity.md `
0 commit comments