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:
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.