Tooling & codegen
tools/ holds build-time code generators wired into build.zig — they run during the build, never ship in artifacts.
island_manifest_gen
Walks app.islands at comptime and prints client_manifest.zig — the table mapping island names to props schemas and wasm chunk URLs. This is why adding an island is just a registry decl + a chunk file: the manifest, SSR marker, and JS hydrator lookup all derive from the same source.
// build.zig wiring (already present):
const gen = b.addRunArtifact(manifest_gen_exe);
const manifest_src = gen.captureStdOut(); // re-runs when islands.zig changesserver_fn_codegen
Walks app.Actions and emits app_client.zig — the typed client-side stubs:
app_client.getCount_call(.{}, onReply); // correlated round-trip
app_client.incrementCount_post(.{}); // fire-and-forget
app_client.getCount_invoke(arena, .{}); // direct (server-side)Signatures derive from the Action's argument struct and return type — change an Action and the stubs (and their call sites) recompile against the new shape.
GL asset tools
| Tool | Purpose |
|---|---|
gl_asset_gen.zig | glTF → .vmesh (mesh + material views) |
gen_demo_glb.zig | generates the demo glTF model |
gen_demo_hdr.zig | generates demo .venv environment maps |
Server opt-in hooks
The server discovers app capabilities with @hasDecl — declare the function and the matching thread/route lights up:
| App decl | Server behavior |
|---|---|
pub fn vizAdvanceTick(buf: []u8) ?[]const u8 | 1 Hz publisher on the viz push channel |
pub fn chatFrameAfter(last_seq: u64, buf: []u8) ?… | 5 Hz drain-and-broadcast on the chat channel |
pub const Actions = struct { … } | /api/<fn> endpoints + client stubs |
pub const islands | island manifest + chunk builds |
Push channels
Any app code running in the server process can broadcast:
/push?channel=<name> streams SSE frames (id:/event:/data:) with ring-buffered history, Last-Event-ID resume, and automatic resync frames when a client falls behind the ring. Channel names: 1–32 chars of [A-Za-z0-9_-]. Chunks subscribe with verve.pushSubscribe(channel, island, export_name).
This documentation site's chat example is the minimal end-to-end reference.