5.7k

Web Engines

Apps that embed web content choose a web engine backend for their WebViews; the app/runtime API is the same across engines. The default is the platform system WebView. On macOS, apps can instead bundle Chromium through CEF. Native-rendered apps carry no web engine at all — this page only applies when a WebView is in the window.

Support Matrix

Platformsystemchromium
macOSWKWebViewCEF, bundled with the app
LinuxWebKitGTKNot wired yet; builds fail early instead of silently using WebKitGTK
WindowsWebView2Not wired yet; builds fail early instead of silently using WebView2

The intended parity contract is the same Zig app model, same runtime services, same builtin bridge commands, same window.zero helper shape, and the same security policy semantics for every engine that a platform supports.

System WebView

.web_engine = "system",

System mode has no bundled browser dependency. It uses the OS web engine, so rendering and web platform support follow the user's installed OS.

On Windows the system engine is WebView2, whose Evergreen runtime is preinstalled on Windows 11 and current Windows 10; older machines need the runtime installer from the WebView2 download page (native doctor checks for it). The build stages the small vendored WebView2Loader.dll next to the app executable automatically, and native package includes it in the Windows artifact.

Chromium (CEF)

Set the app engine once:

.web_engine = "chromium",
.cef = .{ .dir = "third_party/cef/<platform>", .auto_install = false },
native cef install
zig build run

CEF mode is first-class on macOS. It uses the same Native SDK runtime APIs as WKWebView, but bundles Chromium for rendering consistency and a predictable web platform.

Chromium is available through CEF on macOS. Linux can still use WebKitGTK with system, and Windows can use the native system host with system; Linux and Windows Chromium builds fail early until their CEF hosts are implemented.

Native-rendered surfaces stay a system-engine feature: the macOS Chromium host does not implement native child views or gpu_surface compositing, and those operations report unsupported instead of silently no-oping (see Platform Support). Windows, child WebViews, the bridge, keyboard shortcuts, tray, dialogs, clipboard, and app timers behave the same as the system host.

Setup

The happy path is managed by the CLI:

native cef install
native doctor --manifest app.zon

native cef install downloads Native SDK's prepared CEF runtime from GitHub Releases, verifies it, and installs a complete layout. App builds currently consume the macOS layout at third_party/cef/macos; Linux and Windows layouts are reserved for the future CEF hosts. The prepared runtime already includes libcef_dll_wrapper, so app developers do not need CMake or Chromium build knowledge.

The default install uses Native SDK's pinned tested CEF version. Pin that version in your app CI or setup docs with native cef install --version <version>, rerun the install when you intentionally update Chromium, then rebuild and repackage the app. A packaged Chromium app must bundle the same CEF layout the binary was linked against; mismatches usually show up as launch failures or missing framework/resource errors.

You can also opt into one-command local setup from the build:

zig build run

Set .cef = .{ .dir = "third_party/cef/<platform>", .auto_install = true } in app.zon to allow the build/package flow to install the prepared runtime automatically. Manual CEF layouts are still supported with -Dcef-dir=/path/to/cef or .cef.dir. Advanced users can also install directly from official CEF archives with native cef install --source official --allow-build-tools. The expected layout is documented in third_party/cef/README.md.

Core maintainers can build CEF from source with tools/cef/build-from-source.sh when preparing the first runtime release for a version or testing a new CEF branch before publishing it.

Build Overrides

FlagDescription
-Dweb-engine=systemTemporarily use the platform system WebView instead of the manifest default.
-Dweb-engine=chromiumTemporarily use CEF on supported platforms. Currently supported for macOS builds.
-Dcef-dir=pathPath to the CEF distribution directory.
-Dcef-auto-install=trueTemporarily opt into running native cef install during Chromium builds when CEF is missing.

Bundling

zig build cef-bundle -Dcef-dir=/path/to/cef

Local Chromium builds also copy the CEF framework into zig-out/bin/Frameworks when Chromium is selected through app.zon or a one-off flag. Packaging includes the runtime when the manifest or CLI override resolves to Chromium.

For beta distribution, verify the packaged .app contains Chromium Embedded Framework.framework under Contents/Frameworks and that signing covers both the app and embedded framework before notarization.

Smoke Tests

zig build test-webview-cef-smoke -Dplatform=macos -Dweb-engine=chromium
zig build test-package-cef-layout -Dplatform=macos

The Chromium smoke step requires a local CEF layout or -Dcef-auto-install=true. It launches the WebView example under CEF with automation, verifies native.ping over the bridge, and exercises child WebView create/setFrame/navigate/close. The package layout step verifies that a Chromium macOS package contains the framework and resources CEF expects.

zig build test-webview-cef-link builds the WebView example with -Dweb-engine=chromium without running it — the cheapest way to prove the Chromium host still compiles and links after platform-layer changes. scripts/gate.sh fast runs it automatically whenever src/platform/macos/ files change (macOS only; it skips with a warning when no CEF layout is installed).

Choosing An Engine

ConsiderationSystemChromium
Bundle sizeMinimal because the browser is system-provided.Large because CEF is bundled.
Rendering consistencyVaries by OS version.Consistent for apps that ship the same CEF build.
Startup timeFastest startup.Slower startup because CEF initializes Chromium.
Best fitSmall apps, OS-native footprint, minimal dependencies.Apps that need Chromium behavior, complex frontend stacks, or tighter rendering control.

In app.zon

.web_engine = "system",
// or, on supported platforms:
.web_engine = "chromium",
.cef = .{
  .dir = "third_party/cef/<platform>",
  .auto_install = true,
},