@takazudo/zfb-runtime 0.1.0-next.55 → 0.1.0-next.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +103 -0
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -95,6 +95,109 @@ import type { ContentSnapshot } from "@takazudo/zfb-runtime/snapshot";
95
95
  import { ClientRouter } from "@takazudo/zfb-runtime/client-router";
96
96
  ```
97
97
 
98
+ #### Enabling SPA soft-navigation (the runtime ships automatically)
99
+
100
+ Mounting `<ClientRouter />` in your layout `<head>` is normally **all you need**.
101
+ The build detects the usage and automatically ships the client-router runtime to
102
+ the browser — you do **not** have to add a manual `"use client"` bootstrap
103
+ island.
104
+
105
+ ```tsx
106
+ import { ClientRouter } from "@takazudo/zfb-runtime";
107
+
108
+ export default function Layout({ children }) {
109
+ return (
110
+ <html>
111
+ <head>
112
+ <ClientRouter fallback="animate" />
113
+ </head>
114
+ <body>{children}</body>
115
+ </html>
116
+ );
117
+ }
118
+ ```
119
+
120
+ **How the runtime reaches the browser.** `<ClientRouter />` itself only renders
121
+ SSR `<head>` tags. The click/form interception is registered by an `init()` call
122
+ that runs as a side effect when `@takazudo/zfb-runtime/client-router` is imported
123
+ in the browser, guarded so it never runs during SSR:
124
+
125
+ ```ts
126
+ // inside @takazudo/zfb-runtime — client-router.ts
127
+ if (typeof document !== "undefined") {
128
+ init();
129
+ }
130
+ ```
131
+
132
+ To get that side-effect import into the client bundle, zfb's island scanner
133
+ detects when a page transitively reaches `<ClientRouter />` and injects
134
+ `import "@takazudo/zfb-runtime/client-router"` into the islands asset
135
+ (`assets/islands.js`) — **even when the project has no `"use client"` islands of
136
+ its own**. The asset is then loaded on the page, the import runs, and `init()`
137
+ fires on the client with zero boilerplate. (Auto-include added in zfb #289 /
138
+ #307; the runtime is byte-for-byte absent from projects that never reach
139
+ `<ClientRouter />`.)
140
+
141
+ **What counts as a `ClientRouter` usage the scanner detects:**
142
+
143
+ - a named `ClientRouter` import from the `@takazudo/zfb-runtime` barrel —
144
+ `import { ClientRouter } from "@takazudo/zfb-runtime"` (renamed forms like
145
+ `{ ClientRouter as CR }` match on the imported name), or
146
+ - any import or re-export of the `@takazudo/zfb-runtime/client-router` subpath
147
+ (e.g. when you only need `navigate` / `prefetch`), or
148
+ - a named `ClientRouter` imported from a *local* barrel that re-exports the
149
+ runtime via `export * from "@takazudo/zfb-runtime"`.
150
+
151
+ The importing module has to be reachable from a page in `pages/` — that is the
152
+ import graph the scanner walks.
153
+
154
+ **When you need a manual side-effect import.** Detection keys off the *import* of
155
+ `ClientRouter`, and a couple of shapes are deliberately **not** treated as a
156
+ trigger — firing on them would ship the runtime to projects that only reference
157
+ `ClientRouter` as a type or never call it:
158
+
159
+ - a namespace import — `import * as rt from "@takazudo/zfb-runtime"` used as
160
+ `rt.ClientRouter`, and
161
+ - a type-only import — `import type { ClientRouter }` (or `{ type ClientRouter }`).
162
+
163
+ If soft-navigation is not working because your reference takes one of these forms
164
+ (or the mounting module is otherwise not reachable from a page), force the
165
+ runtime in with an explicit side-effect import from a page-reachable
166
+ `"use client"` island. The island renders nothing; running its bundle in the
167
+ browser fires the same `typeof document !== "undefined"` guard (`init()` is
168
+ idempotent, so reaching it again is a no-op):
169
+
170
+ ```tsx
171
+ // src/components/client-router-bootstrap.tsx
172
+ "use client";
173
+ import "@takazudo/zfb-runtime/client-router";
174
+
175
+ export default function ClientRouterBootstrap() {
176
+ return null;
177
+ }
178
+
179
+ // Stable marker name so the SSR marker, the scanner record, and the hydration
180
+ // manifest agree under production minification.
181
+ ClientRouterBootstrap.displayName = "ClientRouterBootstrap";
182
+ ```
183
+
184
+ ```tsx
185
+ import { Island } from "@takazudo/zfb";
186
+ import ClientRouterBootstrap from "@/components/client-router-bootstrap";
187
+
188
+ // Mount once near the end of <body>; when="load" registers the intercepts as
189
+ // soon as the islands runtime starts.
190
+ <Island when="load">
191
+ <ClientRouterBootstrap />
192
+ </Island>;
193
+ ```
194
+
195
+ This is the escape hatch, not the default — prefer a plain
196
+ `import { ClientRouter } from "@takazudo/zfb-runtime"`, which the scanner detects
197
+ on its own. See the [Client-Side Routing concept
198
+ guide](https://takazudomodular.com/pj/zudo-front-builder/docs/concepts/client-side-routing/)
199
+ for the full API.
200
+
98
201
  ### `createPageRouter(options) → PageRouter`
99
202
 
100
203
  Build a fetch-handler that serves the supplied pages. The returned
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takazudo/zfb-runtime",
3
- "version": "0.1.0-next.55",
3
+ "version": "0.1.0-next.56",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "JavaScript runtime for zfb static sites — Hono-backed page router, content snapshots, and client-side hydration.",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": "^19.2.3",
64
- "@takazudo/zfb": "0.1.0-next.55"
64
+ "@takazudo/zfb": "0.1.0-next.56"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "react": {
@@ -75,7 +75,7 @@
75
75
  "react": "^19.2.3",
76
76
  "typescript": "^5.9.0",
77
77
  "vitest": "^2.1.9",
78
- "@takazudo/zfb": "0.1.0-next.55"
78
+ "@takazudo/zfb": "0.1.0-next.56"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsc",