Head management

Any component can contribute to <head> during render; the page shell drains the accumulated entries in priority order before emitting the body. Contributions compose across layouts: a layout sets defaults, a leaf page overrides.

The API

try ctx.setTitle("Pricing — MyApp");      // last writer wins
try ctx.setTitleIfUnset("MyApp");         // layout-friendly default

try ctx.metaTag(.{ .name = "description", .content = "…" });
try ctx.metaTag(.{ .name = "og:title", .content = "…", .is_property = true, .priority = 40 });

try ctx.linkTag(.{ .rel = "canonical", .href = url });
try ctx.linkTag(.{ .rel = "stylesheet", .href = try ctx.assetHref("site.css") });

try ctx.jsonLd("{\"@context\":\"https://schema.org\",…}");

metaTag replaces an existing entry with the same name — re-rendering a layout never duplicates tags. is_property = true emits property= instead of name= (Open Graph). priority orders entries in the drained output.

A complete per-page head

fn renderWork(ctx: *verve.Context) !*verve.Node {
    const slug = ctx.param("slug") orelse "";
    try ctx.setTitle(try std.fmt.allocPrint(ctx.alloc(), "Work — {s}", .{slug}));
    try ctx.metaTag(.{ .name = "description", .content = "Case study." });
    try ctx.linkTag(.{ .rel = "canonical", .href = try std.fmt.allocPrint(
        ctx.alloc(), "https://example.com/work/{s}", .{slug}) });
    try ctx.jsonLd(try std.fmt.allocPrint(ctx.alloc(),
        "{{\"@context\":\"https://schema.org\",\"@type\":\"CreativeWork\",\"name\":\"{s}\"}}",
        .{slug}));
    ...
}

Draining in the shell

The shell renders the accumulator into bytes and embeds them verbatim — this is why head order is stable no matter which component contributed when:

var aw: std.Io.Writer.Allocating = .init(ctx.alloc());
try ctx.head.?.render(&aw.writer);
// → <meta charset>, <title>, metas, links, json-ld — priority-ordered

ctx.el("head").children(.{ ctx.raw(aw.written()), ... })

The accumulator always provides <meta charset> and the title; your shell adds stylesheets and anything static.

Next: Markdown & highlighting.