Zero-Native: Tiny Desktop Apps with Zig, System WebView, and Direct C Interop
Zero-Native is a desktop and mobile application framework built in Zig. The native shell is minimal: it creates a window, hosts a WebView, and provides a bridge between the web UI and native OS APIs. By using the operating system's built-in WebView (WKWebView on macOS, WebView2 on Windows) rather than bundling Chromium, it produces distributable binaries in the single-digit megabyte range. Chromium can be included via the Chromium Embedded Framework when cross-platform rendering consistency is required.
Why Zig for the native layer
Zig's @cImport feature allows direct inclusion of C header files without binding generators or wrapper code. Any C library or OS API is one import away. This makes the native shell straightforward to extend: adding a native capability means writing Zig that calls a C API, not navigating an FFI abstraction layer.
Zig is also simpler than Rust for this use case. There is no borrow checker or lifetime management system. Memory management is manual, which shifts responsibility to the developer, but reduces the conceptual overhead for those coming from higher-level languages.
Architecture comparison: Zero-Native vs. Electrobun
Both Zero-Native and Electrobun aim to be lightweight Electron alternatives, but their architectures differ meaningfully.
Electrobun runs its main process logic in TypeScript inside a Bun web worker. Native OS calls go through Bun's Foreign Function Interface (FFI) into C++/Objective-C code. The path is: TypeScript → Bun runtime (FFI) → C++/Objective-C → OS API.
Zero-Native has no intermediate JavaScript runtime for the main process. The Zig binary is the main process. Native OS calls go directly from Zig to system APIs via @cImport. The path is: Zig → OS API.
Fewer abstraction layers means a smaller binary, less overhead per native call, and a simpler mental model for the native side of the application.
Setup
Prerequisites
Zig is required. On macOS with Homebrew:
Verify:
Install the Zero-Native CLI following the instructions on the Zero-Native website. Once installed, zero-native should be available in your PATH.
Scaffolding a project
--frontend react sets up a Vite + React frontend. Other options include vue, svelte, next, and vite for a vanilla template.
The generated project structure:
app.zon: application configuration in Zig Object Notationassets/: static assets including application iconsbuild.zig: Zig build script defining compilation, linking, and packagingfrontend/: Vite project for the web UIsrc/: Zig source for the native shell
Running the application
This installs frontend dependencies, builds the frontend for production, compiles the Zig shell, and launches the application.
Development server with HMR
For active development, the dev server compiles a debug binary and starts the Vite dev server. Changes to frontend/src/ are reflected instantly via HMR without restarting the application.
Configuration: app.zon
app.zon controls application metadata and behavior. Key settings:
.web_engine accepts "system" (default, uses the OS WebView, smallest binary) or "chromium" (bundles CEF, larger binary, consistent rendering across platforms).
Packaging
Output goes to zig-out/package/. With the system WebView option, the distributable .app bundle in the demonstration was 2.9 MB. Some community projects have produced builds under 680 KB.
Tradeoffs
Zero-Native requires writing Zig to extend the native layer. For developers unfamiliar with systems programming, this is an additional learning investment beyond the web UI work.
The project is relatively early-stage compared to Electron or Electrobun. The feature set and ecosystem are less mature. Using the system WebView means rendering behavior varies between platforms unless CEF is included.
For applications where any of these constraints matter, Zero-Native's tiny binary size and direct architecture are the primary reasons to accept them.
Final thoughts
Zero-Native is the right choice when binary size, startup speed, and native performance are priorities and the team is willing to write a small amount of Zig for native integrations. The @cImport capability makes adding C-based native libraries straightforward, and the direct Zig-to-OS architecture avoids the overhead that accumulates in FFI-layered frameworks.
Documentation and installation instructions are at zero-native.dev.