Site / foldkit-site

The lifecycle wiring

Site.routing is the application's link-click and URL-change lifecycle as one wiring, so update stops hand-writing those two branches:

ts
import { modifyFields } from 'foldkit/struct'

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,
})

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 our own write never re-renders or clears pending state. The application's own update answers nothing for either message; reduces names them for its guard, the way Remote.reduces does. What a new route does beyond setting the field is arrived: (model, route) => ({ model, commands }), run after the routed pages are told and never for an echo: the CMS site moves focus to what it drew there (examples/cms/src/apps/siteApp.ts).

The wiring claims the click tag and shares the change tag with URL mirrors, which read their slices first. CompletedNavigation is one completion for the navigation commands — declare the variant, pass the constructor. Route changes reach child pages through their own Messages only once routed placements land; until then informing them stays hand-written.