Control flow

Conditionals, keyed lists, portals, error boundaries, and slots — the composition tools for node trees.

show — conditional render

const badge = verve.show(ctx, user.is_admin,
    ctx.span().class("badge").text("admin"),
    null); // else-branch optional; null renders nothing

Both branches are evaluated at the call site (it's a function, not a macro) — keep hot branches cheap to build.

forEach — keyed iteration

const Item = struct { id: []const u8, label: []const u8 };

const Helpers = struct {
    fn key(_: void, it: Item) []const u8 { return it.id; }
    fn render(_: void, c: *const verve.Context, it: Item) anyerror!*verve.Node {
        return c.span().text(it.label);
    }
};
const list = try verve.forEach(ctx, Item, items, {}, Helpers.key, Helpers.render);

Produces a <ul class="verve-for"> with one <li data-vkey="<key>"> per item. The keys are what make client-side list reconciliation cheap: the runtime's listDiff moves keyed elements instead of re-creating them — this is also the FLIP-animation fast path.

For full layout control, plain for loops over .children(...) work too — forEach is a convention, not a requirement:

const grid = ctx.div().class("grid").bind("my_list");
for (items) |it| {
    _ = grid.children(.{ctx.div().attr("data-vkey", it.id).text(it.label)});
}

portal — render elsewhere

verve.portal(ctx, "#toasts", ctx.div().class("toast").text("Saved!"))

Server-side the content renders inline (SEO and no-JS clients see it in place) wrapped in <template data-vportal="#toasts">; the client runtime relocates it into the target element on hydrate.

Error boundaries

ctx.errorBoundary(riskyTree, ctx.p().text("Something went wrong."))

If riskyTree's builder chain accumulated an error, the fallback renders instead.

Slots

Slot/SlotMap mark named insertion points inside templates declared with ctx.template(name, inner). Mark inner nodes with .slot("name"); wasm chunks instantiate clones via verve.cloneTemplate(name) and fill them with verve.slotText / verve.slotAttr. This is the zero-hydration path for stamping out repeated client-side structures.

Next: Islands.