3.4 KiB
Frontend and Assets
Use this when working with React, Vue, Svelte, Next.js, Vite, dev servers, HMR, static assets, or packaged frontend output.
Recommended source pattern
Framework apps should use a dynamic source:
fn source(context: *anyopaque) anyerror!native_sdk.WebViewSource {
const self: *App = @ptrCast(@alignCast(context));
return native_sdk.frontend.sourceFromEnv(self.env_map, .{
.dist = "frontend/dist",
.entry = "index.html",
});
}
sourceFromEnv checks NATIVE_SDK_FRONTEND_URL. If set, the WebView loads the dev server URL. If not set, it serves packaged assets from dist.
Manifest frontend config
.frontend = .{
.dist = "frontend/dist",
.entry = "index.html",
.spa_fallback = true,
.dev = .{
.url = "http://127.0.0.1:5173/",
.command = .{ "npm", "--prefix", "frontend", "run", "dev", "--", "--host", "127.0.0.1" },
.ready_path = "/",
.timeout_ms = 30000,
},
},
Fields:
dist: built frontend output path.entry: HTML entry file withindist.spa_fallback: serveentryfor unknown routes.dev.url: local dev server URL.dev.command: command the Native SDK can spawn.dev.ready_path: path to poll for readiness.dev.timeout_ms: readiness timeout.
Dev server workflow
Use:
zig build dev
Or directly:
native dev --manifest app.zon --binary zig-out/bin/MyApp
The dev command starts the frontend process, waits for readiness, sets NATIVE_SDK_FRONTEND_URL, launches the native shell, and terminates the frontend when the shell exits.
Framework defaults:
- Vite, React, Vue, Svelte:
http://127.0.0.1:5173/, commandnpm run dev -- --host 127.0.0.1. - Next.js:
http://127.0.0.1:3000/, commandnpm run dev -- --hostname 127.0.0.1.
Production assets
For packaged builds, serve local assets from zero://app:
return native_sdk.frontend.productionSource(.{
.dist = "frontend/dist",
.entry = "index.html",
});
The package/build flow should build the frontend before packaging. zig build bundle-assets and native bundle-assets copy the configured dist directory into build/package output.
Security and frontend origins
Add exact origins to security.navigation.allowed_origins:
.security = .{
.navigation = .{
.allowed_origins = .{
"zero://app",
"http://127.0.0.1:5173",
},
},
},
Use zero://inline only for inline examples. Do not allow "*" for production navigation.
For packaged HTML, start with a strict CSP:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'">
For dev servers, keep development CSP separate and add only the local dev/WebSocket endpoints required by the framework.
Frontend to native calls
Use:
const result = await window.zero.invoke("native.ping", { source: "webview" });
For builtin windows/WebViews helpers, enable js_window_api and policy in the runner. For custom commands, register handlers in Zig and allow the command in policy.
Example projects
examples/next: Next.js app with production assets underfrontend/out.examples/react: React with Vite.examples/svelte: Svelte with Vite.examples/vue: Vue with Vite.
When unsure about frontend build commands or output directories, inspect the matching example before editing.