Site / Creating a site

The lifecycle wiring: stop hand-writing two branches

Site.routing is the application's link-click and URL-change lifecycle as one wiring:

ts
const Routing = Site.routing<Model, Message, AppRoute>({
  site: AppSite,
  owner: App.owner,
  route: {
    dependency: App.model.route.dependency,
    get: model => model.route,
    set: (model, route) => modifyFields(model, { route: () => route }),
  },
  parse: urlToAppRoute,
  tags: { clicked: 'ClickedLink', changed: 'ChangedUrl' },
  completed: Message.CompletedNavigation,
  pages: [PeoplePage],
})

const assembly = Bundle.assemble([Routing, ...pages])
const update = assembly.update((model, message) =>
  Routing.reduces(message) ? { model } : updateOwn(model, message),
)

A click on a link the tree holds navigates — pushing or replacing per Site.historyOf, computed from the current route, so entries stay entries. Any other link loads, on this origin or not (Site.routeAt): another application serves it. A URL change sets the route field, or returns the same Model when the address parses to the route already shown, so an echo of the application's own write never re-renders or clears pending state. The wiring claims the click tag and shares the change tag with URL mirrors, which read their slices first. pages are routed placements (next section), informed through their own Messages when their route arrives, and arrived: (model, route) => ({ model, commands }) is what the application does after them for a new route (moving focus), never for an echo.