5.7k

Web Content

Native apps can embed WebViews as first-class components: build a web browser, a website builder with live preview, or a doc viewer that renders real web content inside a native-rendered app. The browser example is a complete working browser; the web engines page covers choosing between the platform WebView and bundled Chromium.

The same machinery also carries an entire existing web frontend — a React, Vue, Svelte, or Next.js codebase running in a WebView inside the native shell. That is a migration path next to the default native-rendered UI: reach for it when you are bringing web UI along, not when starting fresh. Scaffold one with native init my_app --frontend <next|vite|react|svelte|vue>.

For frontends with a build step, the Native SDK provides helpers to switch between a dev server during development and bundled assets in production.

Dynamic source function

Use source_fn on your App so development uses a localhost server and production uses bundled assets:

fn source(context: *anyopaque) anyerror!native_sdk.WebViewSource {
    const self: *App = @ptrCast(@alignCast(context));
    return native_sdk.frontend.sourceFromEnv(self.env_map, .{
        .dist = "dist",
        .entry = "index.html",
    });
}

sourceFromEnv checks NATIVE_SDK_FRONTEND_URL. If set, it returns a URL source; otherwise it returns an assets source from config.dist.

frontend.Config

FieldDefaultDescription
dist"dist"Path to the built frontend output
entry"index.html"HTML entry point within dist
origin"zero://app"Origin for asset URLs
spa_fallbacktrueServe entry for unknown routes
dev_url_env"NATIVE_SDK_FRONTEND_URL"Environment variable checked by sourceFromEnv

Configure in app.zon

.frontend = .{
    .dist = "dist",
    .entry = "index.html",
    .spa_fallback = true,
    .dev = .{
        .url = "http://127.0.0.1:5173/",
        .command = .{ "npm", "run", "dev", "--", "--host", "127.0.0.1" },
        .ready_path = "/",
        .timeout_ms = 30000,
    },
}

Dev server

Use native dev to let the Native SDK manage the frontend server lifecycle:

native dev --binary zig-out/bin/MyApp
native dev --binary zig-out/bin/MyApp --url http://127.0.0.1:3000/ --command "npm run dev"

The command starts the frontend process, waits for the port to accept connections, launches the native shell with NATIVE_SDK_FRONTEND_URL, and terminates the frontend when the shell exits. See Dev Server for all flags.

Framework recipes

Vite: .url = "http://127.0.0.1:5173/", command npm run dev -- --host 127.0.0.1.

Next.js: .url = "http://127.0.0.1:3000/", command npm run dev -- --hostname 127.0.0.1.

Static preview: point .dist at the build output and use any local server command.

Examples

The repository includes complete frontend examples:

  • examples/next - Next.js app with frontend/out production assets.
  • examples/react - React app built with Vite.
  • examples/svelte - Svelte app built with Vite.
  • examples/vue - Vue app built with Vite.

Each example can be run from its directory with zig build run, or with zig build dev for the managed frontend dev server flow.

Production source

For packaged builds that always use local assets:

return native_sdk.frontend.productionSource(.{ .dist = "dist", .entry = "index.html" });

NATIVE_SDK_FRONTEND_ASSETS

NATIVE_SDK_FRONTEND_ASSETS is an app-defined convention (not read by the frontend module). Examples use it to signal that pre-built assets should be loaded via productionSource instead of the default dev/prod branching.