Site / Creating a site
Building nodes: options or builder
The options bag above covers the common case. To annotate in steps, or to share an annotation bundle across nodes, build incrementally — the options are sugar over this builder, one implementation:
const Person = Site.node(personRouter, AppRoute.Person)
.title(({ personId }) => `Person ${personId} | Routing`)
.section('People')
.nodeMethods — not pipeable fragments — because each stage of a pipe is a
separate generic call and cannot infer the route, while a method already
knows its node's. Named bundles compose through .pipe (or free pipe)
with no annotation:
const inPeopleSection = <R extends { readonly _tag: string }>(b: NodeBuilder<R>) =>
b.section('People').shortcut(['G', 'P'])
const People = Site.node(peopleRouter, AppRoute.People).pipe(inPeopleSection).nodeRead .node at any stage: every step freezes, so intermediates are usable
nodes too (targets, hrefs), never drafts. The full annotation set is
title, section, landing (the section's nav address, as this node's
params), shortcut (the keys that go to its landing; Site.shortcuts binds them), history (below),
surface (below), layout, and view (below).
Two deliberate absences, both load-bearing. The tag always derives from the
route case — no custom names — because one route case is one node, which is
what keeps chain inspection unambiguous. And there is no SitePlan object,
no Site.prefetch, no prepare: preparation stays caller-composed, as the
data-fetching sections show.