# Web engines

> WebView composition on desktop hosts, CEF tooling and hosts, engine flags, and when native-rendered UI coexists with web content.

- Repository: vercel-labs/native
- GitHub: https://github.com/vercel-labs/native
- Human docs: https://grok-wiki.com/public/docs/vercel-labs-native-8ccc3580636a
- Complete Markdown: https://grok-wiki.com/public/docs/vercel-labs-native-8ccc3580636a/llms-full.txt

## Source Files

- `docs/src/app/web-engines/layout.tsx`
- `src/tooling/cef.zig`
- `src/platform/windows/cef_host.cpp`
- `src/platform/linux/cef_host.cpp`
- `examples/webview/README.md`
- `third_party/cef/README.md`

---

---
title: "Web engines"
description: "WebView composition on desktop hosts, CEF tooling and hosts, engine flags, and when native-rendered UI coexists with web content."
---

Apps that load web content select a backend with `app.zon` field `.web_engine` (`"system"` or `"chromium"`). The Zig app model, bridge commands, navigation policy, and `WebViewSource` load path stay the same; the host implementation and packaging change. Native-rendered apps that never open a WebView do not select or link a web engine.

## Engine values

| Value | Meaning | Default |
| --- | --- | --- |
| `system` | OS WebView (no bundled browser) | Yes (`src/tooling/web_engine.zig` default) |
| `chromium` | Bundled CEF runtime | No |

Resolution order: build/CLI override → `app.zon` → default. Invalid values (for example `"blink"`) fail resolution with `InvalidWebEngine`.

```zig
// app.zon
.web_engine = "system",
// or on a supported Chromium host:
.web_engine = "chromium",
.cef = .{
  .dir = "third_party/cef/macos",
  .auto_install = false,
},
```

## Platform matrix

| Platform | `system` host | `chromium` host | Build gate |
| --- | --- | --- | --- |
| macOS | `appkit_host.m` + WKWebView | `cef_host.mm` + CEF | Chromium supported |
| Linux | `gtk_host.c` + WebKitGTK 6.0 | `cef_host.cpp` (layout/link path) | `-Dweb-engine=chromium` panics unless `-Dplatform=macos` |
| Windows | `webview2_host.cpp` + WebView2 | `cef_host.cpp` is a placeholder that includes the WebView2 host | Same macOS-only chromium panic; doctor reports Chromium unsupported |

The top-level and example build graphs enforce:

```text
-Dweb-engine=chromium currently requires -Dplatform=macos
```

Use `system` on Linux and Windows. Do not expect silent fallback to WebKitGTK/WebView2 when Chromium is requested on those platforms.

## Host selection

```text
app.zon .web_engine / -Dweb-engine
            │
            ▼
   resolve (manifest + overrides)
            │
     ┌──────┴──────┐
     ▼             ▼
  system        chromium
     │             │
  link OS       CEF layout check
  WebView       (optional native cef install)
  host source   + platform CEF host
```

| Platform | Engine | Host source | Link notes |
| --- | --- | --- | --- |
| macOS | system | `src/platform/macos/appkit_host.m` | WebKit framework |
| macOS | chromium | `src/platform/macos/cef_host.mm` | CEF includes, `libcef_dll_wrapper.a`, Chromium Embedded Framework, rpath `@executable_path/Frameworks` |
| Linux | system | `src/platform/linux/gtk_host.c` | gtk4, webkitgtk-6.0 |
| Linux | chromium | `src/platform/linux/cef_host.cpp` | CEF include/dir checks present; runtime selection blocked at build |
| Windows | system | `src/platform/windows/webview2_host.cpp` | Needs WebView2 SDK headers; without them WebView loads report `WebViewNotFound` |
| Windows | chromium | `src/platform/windows/cef_host.cpp` | Placeholder; not a real CEF browser host |

## Feature parity by engine

The public platform feature set is engine-gated. Unsupported paths return explicit errors (for example `UnsupportedService`, `UnsupportedViewKind`, `UnsupportedChildWebViews`) rather than silent no-ops.

### macOS

| Feature | system | chromium |
| --- | --- | --- |
| Main WebView, child WebViews | Yes | Yes |
| Tray, shortcuts, dialogs, clipboard, credentials, notifications | Yes | Yes |
| Native views, native control commands, app menus | Yes | No |
| GPU surfaces / scroll drivers / view-surface adoption | Yes | No |
| File drops | Yes | No |
| Audio playback / streaming / spectrum | Yes | No |

### Linux

| Feature | system | chromium (when linked) |
| --- | --- | --- |
| Main WebView | Yes | Host APIs exist; child WebViews return `UnsupportedChildWebViews` |
| Native views, GPU surfaces, menus, credentials, audio | Yes (where host provides them) | No (`web_engine == .system` required) |

### Windows

| Feature | system | chromium |
| --- | --- | --- |
| Main / child WebViews | Yes (WebView2 when installed) | Feature probes report unsupported |
| Native views, menus, GPU surfaces, audio | Yes on system host | No |

## WebView composition

Web content is not the default UI path. Two composition models coexist with native-rendered UI:

### WebView shell (window is mostly web)

- Startup window loads a `WebViewSource` (`html`, `url`, or `assets`).
- Reserved main label is `main`.
- Child WebViews use unique labels per parent window; global cap is `max_webviews` (16).
- Child options: `label`, `url`, `frame`, `layer`, `transparent`, `bridge_enabled`.
- Higher `layer` stacks above lower layers at the native host; DOM `z-index` does not cross WebViews.
- `bridge_enabled: true` injects the bridge only for trusted surfaces; leave false for untrusted pages.

```zig
// Platform services shape (runtime → host)
// createWebView(WebViewOptions{
//   .window_id = 1,
//   .label = "preview",
//   .url = "https://example.com",
//   .frame = geometry.RectF.init(24, 24, 420, 260),
//   .layer = 10,
//   .bridge_enabled = false,
// })
```

### Canvas + web pane (native UI owns the window)

`UiApp` can drive up to `max_web_panes` (4) panes via `Options.web_panes`. Each pane maps a scene webview label to a layout anchor (or explicit frame) and a URL under `security.navigation.allowed_origins`. This is the path for one live web region beside engine-drawn widgets on a system host that supports native views and GPU surfaces.

<Warning>
Chromium on macOS does not implement native child views or `gpu_surface` compositing. Canvas + web-pane and native-control coexistence require `web_engine = "system"`.
</Warning>

### Source kinds

| Kind | Constructor | Use |
| --- | --- | --- |
| `html` | `WebViewSource.html(bytes)` | Inline document (window source budget up to 65536 bytes) |
| `url` | `WebViewSource.url(bytes)` | Remote or local URL |
| `assets` | `WebViewSource.assets(.{ .root_path, .entry, .origin, .spa_fallback })` | Packaged frontend tree; default origin `zero://app` |

Navigation and create paths check `security.navigation.allowed_origins` before the host creates or navigates a view.

## Configure the engine

### Manifest

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `.web_engine` | `"system"` \| `"chromium"` | `"system"` | Selects host backend |
| `.cef.dir` | path | `third_party/cef/macos` | Platform defaults rewrite bare macOS path to `linux` / `windows` subdirs when building for those platforms |
| `.cef.auto_install` | bool | `false` | When true and Chromium is selected, build may run `native cef install --dir <dir>` |

Also declare web-related capabilities when the app uses them (example: `webview`, `js_bridge` in `examples/webview/app.zon`).

### Build overrides

| Flag | Effect |
| --- | --- |
| `-Dweb-engine=system` | Force system host for this build |
| `-Dweb-engine=chromium` | Force CEF; requires macOS platform today |
| `-Dcef-dir=<path>` | CEF root for includes, wrapper, and runtime files |
| `-Dcef-auto-install=true` | Install prepared CEF during Chromium builds if missing |

CLI doctor accepts the same idea: `--web-engine`, `--cef-dir`, `--cef-auto-install`.

## CEF tooling

CEF binaries are not vendored in git. Install a prepared runtime (includes `libcef_dll_wrapper`) or, for advanced setups, official CEF archives plus a local wrapper build.

### Commands

```bash
native cef install
native cef install --dir third_party/cef/macos
native cef install --version 144.0.6+g5f7e671+chromium-144.0.7559.59
native cef install --source official --allow-build-tools --dir /path/to/cef
native cef path [--dir path]
native cef doctor [--dir path]
native cef prepare-release [--dir path] [--output path] [--version version]
```

| Command | Role |
| --- | --- |
| `install` | Download/verify/extract prepared (default) or official CEF |
| `path` | Print resolved install directory |
| `doctor` | Verify required layout entries for the host platform |
| `prepare-release` | Maintainer packaging of a release archive |

Pinned default prepared version: `144.0.6+g5f7e671+chromium-144.0.7559.59` (from `src/tooling/cef.zig`). Prepared archives download from the configured GitHub Releases base as `native-sdk-cef-<version>-<platform>.tar.gz`.

### Required layout

| Platform | Required entries |
| --- | --- |
| macOS | `include/cef_app.h`, `Release/Chromium Embedded Framework.framework/`, `libcef_dll_wrapper/libcef_dll_wrapper.a` |
| Linux | `include/cef_app.h`, `Release/libcef.so`, `libcef_dll_wrapper/libcef_dll_wrapper.a` |
| Windows | `include/cef_app.h`, `Release/libcef.dll`, `libcef_dll_wrapper/libcef_dll_wrapper.lib` |

Default dirs: `third_party/cef/macos`, `third_party/cef/linux`, `third_party/cef/windows`.

Cache directories used during download: macOS `~/Library/Caches/native/cef`, Linux `~/.cache/native/cef` (or `$XDG_CACHE_HOME/native/cef`), Windows `%LOCALAPPDATA%/native/cef`.

### Maintainer path

```bash
tools/cef/build-from-source.sh --platform macosarm64 --cef-branch <branch> --output zig-out/cef
```

Uses CEF `automate-git.py`, depot_tools, CMake, and the platform toolchain. App developers should use `native cef install`, not source builds.

### Local run bundling (macOS Chromium)

Chromium runs copy the CEF framework into `zig-out/bin/Frameworks` (and related layout paths) and stage helper libraries next to the executable. Packaging must ship the same CEF layout the binary was linked against.

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

## Example: WebView app

`examples/webview` declares `.web_engine = "system"`, bridge commands including `native.ping` and `native-sdk.webview.*`, and allowed origins for inline, app, and example.com content.

```bash
# From examples/webview
zig build run

# Chromium on macOS
zig build run -Dweb-engine=chromium -Dcef-auto-install=true

# Automation-enabled run
zig build run -Dautomation=true
```

Verification signals for Chromium smoke (`zig build test-webview-cef-smoke -Dplatform=macos -Dweb-engine=chromium`): automation ready, `webview.load` in logs, `native.ping` returns success with pong payload, child WebView create/setFrame/navigate/close succeed.

## Verify setup

```bash
native doctor --manifest app.zon
native doctor --manifest app.zon --web-engine chromium --cef-dir third_party/cef/macos
native cef doctor --dir third_party/cef/macos

# Cheapest Chromium host compile check (macOS, needs CEF layout)
zig build test-webview-cef-link

# Package layout contains framework/resources
zig build test-package-cef-layout -Dplatform=macos
```

`scripts/gate.sh fast` runs `cef-host-link` when `src/platform/macos/` changes. If the CEF layout is absent, the gate warns and skips rather than falsely green-lighting Chromium host compile.

Doctor checks include:

| Check id | Meaning |
| --- | --- |
| `webview-system` | OS backend present (WKWebView / WebKitGTK 6.0 / WebView2 registry probe) |
| `webview-chromium` | CEF layout ready, available but not selected, or unsupported on host |
| `webview-config` | Manifest/override resolution succeeded |

## When to use which engine

| Consideration | system | chromium (macOS) |
| --- | --- | --- |
| Bundle size | Minimal | Large (bundled CEF) |
| Rendering consistency | Follows OS version | Fixed CEF build |
| Startup | Fastest | CEF init cost |
| Native canvas coexistence | Full system feature set | No native views / GPU surfaces |
| Best fit | OS footprint, hybrid native+web, Linux/Windows | Chromium-stable web platform, complex frontend stacks that only need WebView chrome |

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Build panics: chromium requires macOS | Linux/Windows `-Dweb-engine=chromium` | Use `system` or build with `-Dplatform=macos` |
| `missing CEF dependency for -Dweb-engine=chromium` | Incomplete layout | `native cef install --dir <cef-dir>` or `-Dcef-auto-install=true` |
| Doctor `webview-chromium` missing | Missing header, framework/so/dll, or wrapper | Install prepared runtime; re-run `native cef doctor` |
| Launch fails after package | Framework/resources not bundled or mismatched CEF | Rebuild package with Chromium resolved; verify `Contents/Frameworks/Chromium Embedded Framework.framework` |
| `WebViewNotFound` on Windows system | WebView2 headers/runtime missing | Install WebView2 runtime; ensure SDK headers for full host |
| Child WebView errors under Chromium on Linux | Explicit `UnsupportedChildWebViews` | Stay on system WebKitGTK for multi-WebView |
| Native views / GPU surface fail under Chromium | Feature gated to system host | Set `.web_engine = "system"` for hybrid UI |
| Official CEF install fails without CMake | Wrapper build required | Use prepared source, or `--source official --allow-build-tools` with CMake installed |

## Related pages

<CardGroup>
  <Card title="Bridge and builtin commands" href="/bridge">
    Host-to-content payloads, async dispatch, builtin webview/window commands, and origin permissions.
  </Card>
  <Card title="Frontend projects" href="/frontend">
    Managed React, Next, Svelte, and Vue shells, asset pipeline, and dev-server integration into WebViews.
  </Card>
  <Card title="Windows and surfaces" href="/windows-surfaces">
    Multi-window composition, GPU surfaces, and host presentation alongside optional web content.
  </Card>
  <Card title="Native UI markup" href="/native-ui">
    Engine-drawn views and `web_panes` for a live WebView region inside a native scene.
  </Card>
  <Card title="Platform support and security" href="/platform-security">
    Host capability matrix and navigation/bridge security boundaries for WebView apps.
  </Card>
  <Card title="Packaging" href="/packaging">
    Bundle layout for system and Chromium apps, including CEF framework placement.
  </Card>
  <Card title="Code signing" href="/code-signing">
    Signing constraints for macOS apps that embed Chromium Embedded Framework.
  </Card>
  <Card title="CLI reference" href="/cli-reference">
    `native cef`, `native doctor`, and build-related flags used with web engines.
  </Card>
</CardGroup>
