macOS · Linux · Windows · iOS · Android
Toolkit for building
native desktop apps
Write your interface in native markup and Zig. The toolkit's own engine renders it into real OS windows — no browser, no WebView.
$ npm install -g @native-sdk/cli
Every app on this page — engine, widgets, renderer — as one static release binary.
From launch to the first frame on the glass — 71–131 ms warm across these apps on macOS arm64.
Embedded browsers, script engines, or interpreters inside those binaries.
Measured in this repository: zig build -Doptimize=ReleaseFast on macOS arm64; launch is process spawn to first presented frame.
Principles
Beautiful by default. Customizable by design.
Native SDK exists because expressive UI and native performance should not be competing goals. Developers often choose web-based runtimes because they offer freedom, speed and control over the product experience. But that freedom often comes with a heavy runtime. Native SDK keeps the expressive authoring model and replaces the runtime with native rendering.


The same toolkit. The same player. Two identities.
Every difference between examples/soundboard and examples/deck is design tokens and a chrome pass — same widgets, same engine. One is an airy app window that follows the site theme; the other is a dense 512×264 enamel-and-glass hardware unit with one finish by design.
Beautiful by default
Great software should not start from a blank slate.
Customizable by design
Your app should have its own identity, not ours.
Native from the start
Every interface is rendered without a browser or WebView.
Predictable state
State changes should be explicit, inspectable and easy to reason about.
Simple authoring
Interfaces should be easy to read, easy to write and easy to generate.
AI is part of the workflow
Native SDK is designed for a world where humans and AI agents build software together.
Predictable by design
Events. Messages. State. Interface.
Events produce messages, messages update state, and state renders the interface — simple to debug, simple to maintain, and simple for AI to generate. This is examples/ui-inbox from the repository: the whole UI is one declarative view, and one update function is the only place state changes. Mistakes in a view are compile errors with line and column, and in dev you edit the view while the app runs, keeping state.
<column background="background">
<row height="{header_height}" padding="12" gap="10" cross="center"
background="surface" window-drag="true" label="Inbox header">
<spacer width="{chrome_leading}" />
<spacer grow="1" />
<if test="{doneCount}">
<button variant="ghost" on-press="clear_done">Clear done</button>
</if>
</row>
<separator />
<column grow="1" gap="12" padding="16">
<row gap="8" cross="center">
<text-field text="{draft}" placeholder="New task…"
on-input="draft_edit" on-submit="add" grow="1" />
<button variant="primary" on-press="add">Add task</button>
</row>
<tabs gap="8">
<for each="filters" as="f">
<button size="sm" selected="{f == filter}"
on-press="set_filter:{f}">{f}</button>
</for>
</tabs>
<scroll grow="1">
<column gap="2">
<for each="visible" key="id" as="t">
<row gap="8" padding="6" cross="center">
<checkbox checked="{t.done}" on-toggle="toggle:{t.id}"
label="Done" />
<text grow="1">{t.title}</text>
</row>
</for>
</column>
</scroll>
</column>
<status-bar>{openCount} open · {doneCount} done</status-bar>
</column>pub const Msg = union(enum) {
add,
toggle: u32,
set_filter: Filter,
clear_done,
draft_edit: canvas.TextInputEvent,
chrome_changed: native_sdk.WindowChrome,
};
pub fn update(model: *Model, msg: Msg) void {
switch (msg) {
.add => {
if (model.draftEmpty()) {
model.addGeneratedTask();
} else {
model.addTask(std.mem.trim(u8, model.draft(), " "));
model.draft_buffer.clear();
}
},
.toggle => |id| if (model.taskById(id)) |task| {
task.done = !task.done;
},
.set_filter => |filter| model.filter = filter,
.clear_done => model.clearDone(),
.draft_edit => |edit| model.draft_buffer.apply(edit),
.chrome_changed => |chrome| {
model.chrome_leading = chrome.insets.left;
model.header_height =
@max(header_natural_height, chrome.insets.top);
},
}
}
Built for modern apps
Seven real apps, in the repo
Dashboards, editors, tools, internal apps, creative software — every screenshot is rendered by Native SDK’s deterministic engine from the example apps in examples/, the same state captured once per color scheme. Flip the site theme and the apps flip with it — deck alone stays dark, by design.

A split-pane editor whose preview is native widgets.
Headings, tables, task lists, links, and blockquotes on the right are ordinary widgets rendered live from the editor on the left — keystroke for keystroke, with no WebView and no HTML.
Native from the start
Feels native because it is
Native SDK owns its renderer — no embedded browser, no heavy runtime pretending to be native. One engine draws every widget into real OS windows, and the parts users touch stay with the operating system: scrolling carries OS momentum, menus are real menus, and the tray is the real tray.
Native UI Guide →momentum and rubber-band overscroll on macOS
declare one menu in markup or Zig; the OS presents it natively, with an automatic anchored fallback
app menus and menu-bar extras driven by the model
native open/save panels and drop events as messages
real text input on macOS, Linux, and Windows
crisp scale-factor-aware pixels on every display
$ native automate wait$ native automate snapshotrole=button name="Add task" …$ native automate widget-click canvas 3$ native automate assert 'gpu_nonblank=true'$ native automate screenshot
AI is part of the workflow
Built to be written by AI agents
Declarative markup and one typed update function make a surface agents author reliably — and the repository ships an agent skill that teaches all of it. Every app embeds an automation server, so any agent can see and drive the running window: snapshots, assertions, input, screenshots. An eval harness hands a clean agent a scaffolded workspace and grades the result — builds, markup checks, live snapshots, and an LLM judge.
Automation →One binary
The whole app is one small file
Markup compiles into the executable, so release builds carry no parser, no interpreter, and no scripting engine — just your logic and the engine, linking the system’s own frameworks. Effects run HTTP fetches, process spawns, file I/O, and timers off the loop; results come back into update as plain messages. And when part of your product is the web, WebView panes coexist with the canvas in the same window.
$ zig build -Doptimize=ReleaseFast$ ls -lh */zig-out/bin3.6M calculator4.2M deck3.6M feed3.5M markdown-viewer3.5M notes5.7M soundboard3.7M system-monitor
Cross-platform
One SDK, desktop and mobile
One codebase compiles for macOS, Linux, Windows, iOS, and Android. Desktop is the mature surface; mobile is experimental — verified on the simulator and emulator, with APIs and tooling still evolving. These statuses describe what ships and is verified today — not a roadmap.
macOS
NativeMetal presentation, OS scroll physics, native context menus, menus, tray, and dialogs. The primary development platform.
Linux
Software presentationGTK windows driven by the deterministic software renderer, with pointer, keyboard, scroll, IME composition, and HiDPI.
Windows
Software presentationWin32 host with IME composition. Cross-compiled and exercised in CI under Wine, including real input injection.
iOS
ExperimentalApps compile into an embed library and present via CAMetalLayer. Verified on the iOS Simulator; device support is in progress.
Android
ExperimentalCross-compiles with the full embed ABI and a NativeActivity shim. On-device runs are not yet verified.
WebViews
CoexistingSystem WebView apps and panes on macOS, Linux, and Windows; bundled Chromium (CEF) on macOS.
Build something native
Scaffold an app, open a real window, and edit the view while it runs.
$ native init my_app$ cd my_app && native deva real window opens — edit src/app.native while it runs

