First request
- Hono matches the route.
- Layout loaders run outside-in, then the page loader.
- React renders HTML with
renderToString. - Loader data is written to
window.__BR_DATA__. - The browser hydrates
#app.
src/routes/_document.tsx or the default shell. Client navigations leave that shell in place and only swap #app. See Layouts.
Later navigation
<Link href="/about"> intercepts the click (plain left click, no modifier keys), requests JSON with x-better-router-navigate: 1, and swaps the page component.
<Form> uses the same JSON channel. Island pages and spa = false routes do a full document load instead.
Modes
Island pages and regular pages can live in the same app. Navigating to an island page does a full load because there is no SPA payload for that route.
CSS and client-only code
Import CSS from a layout or document. Vite injects it in dev; the client build emits hashed assets..tsx page. Put that work in .server.tsx.
Payload
window.__BR_DATA__ is the SPA payload:
useLoaderData() reads props. Layouts receive their own layoutProps[i] as React props, not through the hook.