@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1c0bdfad

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 (406) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +291 -61
  3. package/dist/bin/rango.js +544 -143
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3744 -1329
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +67 -13
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +312 -0
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +247 -23
  12. package/skills/caching/SKILL.md +322 -19
  13. package/skills/composability/SKILL.md +27 -2
  14. package/skills/css/SKILL.md +76 -0
  15. package/skills/debug-manifest/SKILL.md +4 -2
  16. package/skills/document-cache/SKILL.md +78 -55
  17. package/skills/handler-use/SKILL.md +364 -0
  18. package/skills/hooks/SKILL.md +282 -60
  19. package/skills/host-router/SKILL.md +278 -0
  20. package/skills/i18n/SKILL.md +276 -0
  21. package/skills/intercept/SKILL.md +50 -6
  22. package/skills/layout/SKILL.md +35 -9
  23. package/skills/links/SKILL.md +249 -17
  24. package/skills/loader/SKILL.md +297 -31
  25. package/skills/middleware/SKILL.md +52 -13
  26. package/skills/migrate-nextjs/SKILL.md +584 -0
  27. package/skills/migrate-react-router/SKILL.md +771 -0
  28. package/skills/mime-routes/SKILL.md +28 -1
  29. package/skills/observability/SKILL.md +172 -0
  30. package/skills/parallel/SKILL.md +203 -7
  31. package/skills/prerender/SKILL.md +155 -111
  32. package/skills/rango/SKILL.md +251 -23
  33. package/skills/react-compiler/SKILL.md +168 -0
  34. package/skills/response-routes/SKILL.md +123 -48
  35. package/skills/route/SKILL.md +104 -9
  36. package/skills/router-setup/SKILL.md +124 -11
  37. package/skills/scripts/SKILL.md +179 -0
  38. package/skills/server-actions/SKILL.md +775 -0
  39. package/skills/streams-and-websockets/SKILL.md +283 -0
  40. package/skills/tailwind/SKILL.md +27 -3
  41. package/skills/testing/SKILL.md +125 -222
  42. package/skills/testing/bindings.md +103 -0
  43. package/skills/testing/cache-prerender.md +127 -0
  44. package/skills/testing/client-components.md +124 -0
  45. package/skills/testing/e2e-parity.md +125 -0
  46. package/skills/testing/flight.md +91 -0
  47. package/skills/testing/handles.md +129 -0
  48. package/skills/testing/loader.md +128 -0
  49. package/skills/testing/middleware.md +99 -0
  50. package/skills/testing/render-handler.md +121 -0
  51. package/skills/testing/response-routes.md +95 -0
  52. package/skills/testing/reverse-and-types.md +84 -0
  53. package/skills/testing/server-actions.md +107 -0
  54. package/skills/testing/server-tree.md +128 -0
  55. package/skills/testing/setup.md +123 -0
  56. package/skills/typesafety/SKILL.md +357 -52
  57. package/skills/use-cache/SKILL.md +46 -14
  58. package/skills/view-transitions/SKILL.md +294 -0
  59. package/src/__augment-tests__/augment.ts +81 -0
  60. package/src/__augment-tests__/augmented.check.ts +116 -0
  61. package/src/__internal.ts +67 -40
  62. package/src/bin/rango.ts +18 -0
  63. package/src/browser/action-coordinator.ts +53 -36
  64. package/src/browser/action-fence.ts +47 -0
  65. package/src/browser/app-shell.ts +39 -0
  66. package/src/browser/app-version.ts +14 -0
  67. package/src/browser/connection-warmup.ts +134 -0
  68. package/src/browser/cookie-name.ts +140 -0
  69. package/src/browser/event-controller.ts +197 -150
  70. package/src/browser/history-state.ts +21 -0
  71. package/src/browser/index.ts +3 -3
  72. package/src/browser/invalidate-client-cache.ts +52 -0
  73. package/src/browser/link-interceptor.ts +4 -0
  74. package/src/browser/navigation-bridge.ts +200 -30
  75. package/src/browser/navigation-client.ts +217 -58
  76. package/src/browser/navigation-store-handle.ts +38 -0
  77. package/src/browser/navigation-store.ts +76 -67
  78. package/src/browser/navigation-transaction.ts +18 -66
  79. package/src/browser/network-error-handler.ts +34 -7
  80. package/src/browser/partial-update.ts +187 -112
  81. package/src/browser/prefetch/cache.ts +312 -30
  82. package/src/browser/prefetch/fetch.ts +344 -47
  83. package/src/browser/prefetch/policy.ts +6 -0
  84. package/src/browser/prefetch/queue.ts +126 -20
  85. package/src/browser/prefetch/resource-ready.ts +77 -0
  86. package/src/browser/rango-state.ts +158 -76
  87. package/src/browser/react/Link.tsx +125 -18
  88. package/src/browser/react/NavigationProvider.tsx +135 -120
  89. package/src/browser/react/ScrollRestoration.tsx +10 -6
  90. package/src/browser/react/context.ts +7 -2
  91. package/src/browser/react/filter-segment-order.ts +66 -7
  92. package/src/browser/react/index.ts +0 -48
  93. package/src/browser/react/location-state-shared.ts +178 -8
  94. package/src/browser/react/location-state.ts +39 -14
  95. package/src/browser/react/use-action.ts +6 -15
  96. package/src/browser/react/use-handle.ts +23 -69
  97. package/src/browser/react/use-href.tsx +8 -1
  98. package/src/browser/react/use-link-status.ts +33 -8
  99. package/src/browser/react/use-navigation.ts +32 -7
  100. package/src/browser/react/use-params.ts +20 -10
  101. package/src/browser/react/use-reverse.ts +106 -0
  102. package/src/browser/react/use-router.ts +46 -11
  103. package/src/browser/react/use-search-params.ts +0 -5
  104. package/src/browser/react/use-segments.ts +11 -21
  105. package/src/browser/response-adapter.ts +80 -5
  106. package/src/browser/rsc-router.tsx +226 -75
  107. package/src/browser/scroll-restoration.ts +54 -42
  108. package/src/browser/segment-reconciler.ts +36 -9
  109. package/src/browser/segment-structure-assert.ts +2 -2
  110. package/src/browser/server-action-bridge.ts +619 -442
  111. package/src/browser/types.ts +115 -11
  112. package/src/browser/validate-redirect-origin.ts +43 -16
  113. package/src/build/collect-fallback-refs.ts +107 -0
  114. package/src/build/generate-manifest.ts +65 -40
  115. package/src/build/generate-route-types.ts +7 -1
  116. package/src/build/index.ts +8 -2
  117. package/src/build/prefix-tree-utils.ts +123 -0
  118. package/src/build/route-trie.ts +182 -37
  119. package/src/build/route-types/ast-route-extraction.ts +15 -8
  120. package/src/build/route-types/codegen.ts +16 -5
  121. package/src/build/route-types/include-resolution.ts +125 -24
  122. package/src/build/route-types/param-extraction.ts +6 -3
  123. package/src/build/route-types/per-module-writer.ts +22 -6
  124. package/src/build/route-types/router-processing.ts +392 -106
  125. package/src/build/route-types/scan-filter.ts +9 -2
  126. package/src/build/route-types/source-scan.ts +216 -0
  127. package/src/build/runtime-discovery.ts +9 -20
  128. package/src/cache/cache-error.ts +104 -0
  129. package/src/cache/cache-key-utils.ts +29 -13
  130. package/src/cache/cache-policy.ts +108 -34
  131. package/src/cache/cache-runtime.ts +214 -48
  132. package/src/cache/cache-scope.ts +236 -89
  133. package/src/cache/cache-tag.ts +103 -0
  134. package/src/cache/cf/cf-base64.ts +33 -0
  135. package/src/cache/cf/cf-cache-constants.ts +127 -0
  136. package/src/cache/cf/cf-cache-store.ts +2224 -171
  137. package/src/cache/cf/cf-cache-types.ts +349 -0
  138. package/src/cache/cf/cf-kv-utils.ts +46 -0
  139. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  140. package/src/cache/cf/index.ts +11 -17
  141. package/src/cache/document-cache.ts +89 -27
  142. package/src/cache/handle-snapshot.ts +70 -0
  143. package/src/cache/index.ts +11 -20
  144. package/src/cache/memory-segment-store.ts +136 -37
  145. package/src/cache/profile-registry.ts +31 -31
  146. package/src/cache/read-through-swr.ts +41 -11
  147. package/src/cache/segment-codec.ts +9 -17
  148. package/src/cache/tag-invalidation.ts +230 -0
  149. package/src/cache/taint.ts +55 -0
  150. package/src/cache/types.ts +37 -100
  151. package/src/client.rsc.tsx +45 -21
  152. package/src/client.tsx +120 -336
  153. package/src/cloudflare/index.ts +11 -0
  154. package/src/cloudflare/tracing.ts +109 -0
  155. package/src/component-utils.ts +19 -0
  156. package/src/components/DefaultDocument.tsx +8 -2
  157. package/src/context-var.ts +84 -2
  158. package/src/debug.ts +2 -2
  159. package/src/decode-loader-results.ts +52 -0
  160. package/src/defer.ts +196 -0
  161. package/src/deps/ssr.ts +0 -1
  162. package/src/encode-kv.ts +49 -0
  163. package/src/errors.ts +30 -4
  164. package/src/escape-script.ts +52 -0
  165. package/src/handle.ts +70 -22
  166. package/src/handles/MetaTags.tsx +56 -19
  167. package/src/handles/Scripts.tsx +183 -0
  168. package/src/handles/breadcrumbs.ts +95 -0
  169. package/src/handles/is-thenable.ts +19 -0
  170. package/src/handles/meta.ts +51 -40
  171. package/src/handles/script.ts +244 -0
  172. package/src/host/cookie-handler.ts +9 -60
  173. package/src/host/errors.ts +0 -24
  174. package/src/host/index.ts +8 -5
  175. package/src/host/pattern-matcher.ts +23 -52
  176. package/src/host/router.ts +107 -99
  177. package/src/host/testing.ts +40 -27
  178. package/src/host/types.ts +37 -4
  179. package/src/host/utils.ts +1 -1
  180. package/src/href-client.ts +137 -22
  181. package/src/index.rsc.ts +79 -29
  182. package/src/index.ts +149 -65
  183. package/src/internal-debug.ts +11 -10
  184. package/src/loader-store.ts +500 -0
  185. package/src/loader.rsc.ts +20 -13
  186. package/src/loader.ts +12 -11
  187. package/src/missing-id-error.ts +68 -0
  188. package/src/outlet-context.ts +1 -1
  189. package/src/outlet-provider.tsx +1 -5
  190. package/src/prerender/param-hash.ts +16 -16
  191. package/src/prerender/store.ts +63 -26
  192. package/src/prerender.ts +198 -82
  193. package/src/redirect-origin.ts +100 -0
  194. package/src/regex-escape.ts +8 -0
  195. package/src/render-error-thrower.tsx +20 -0
  196. package/src/response-utils.ts +62 -0
  197. package/src/reverse.ts +65 -15
  198. package/src/root-error-boundary.tsx +1 -19
  199. package/src/route-content-wrapper.tsx +7 -72
  200. package/src/route-definition/dsl-helpers.ts +469 -276
  201. package/src/route-definition/helper-factories.ts +29 -139
  202. package/src/route-definition/helpers-types.ts +113 -37
  203. package/src/route-definition/index.ts +3 -3
  204. package/src/route-definition/redirect.ts +53 -12
  205. package/src/route-definition/resolve-handler-use.ts +161 -0
  206. package/src/route-definition/use-item-types.ts +32 -0
  207. package/src/route-map-builder.ts +7 -17
  208. package/src/route-types.ts +37 -41
  209. package/src/router/basename.ts +14 -0
  210. package/src/router/content-negotiation.ts +164 -17
  211. package/src/router/error-handling.ts +45 -18
  212. package/src/router/find-match.ts +45 -22
  213. package/src/router/handler-context.ts +110 -39
  214. package/src/router/instrument.ts +350 -0
  215. package/src/router/intercept-resolution.ts +50 -24
  216. package/src/router/lazy-includes.ts +19 -53
  217. package/src/router/loader-resolution.ts +274 -56
  218. package/src/router/logging.ts +5 -8
  219. package/src/router/manifest.ts +49 -45
  220. package/src/router/match-api.ts +121 -205
  221. package/src/router/match-context.ts +0 -22
  222. package/src/router/match-handlers.ts +58 -58
  223. package/src/router/match-middleware/background-revalidation.ts +33 -6
  224. package/src/router/match-middleware/cache-lookup.ts +214 -263
  225. package/src/router/match-middleware/cache-store.ts +73 -33
  226. package/src/router/match-middleware/intercept-resolution.ts +8 -28
  227. package/src/router/match-middleware/segment-resolution.ts +52 -18
  228. package/src/router/match-pipelines.ts +1 -42
  229. package/src/router/match-result.ts +104 -49
  230. package/src/router/metrics.ts +217 -26
  231. package/src/router/middleware-types.ts +24 -110
  232. package/src/router/middleware.ts +384 -197
  233. package/src/router/navigation-snapshot.ts +131 -0
  234. package/src/router/params-util.ts +23 -0
  235. package/src/router/pattern-matching.ts +148 -91
  236. package/src/router/prefetch-cache-ttl.ts +51 -0
  237. package/src/router/prerender-match.ts +199 -56
  238. package/src/router/preview-match.ts +32 -102
  239. package/src/router/request-classification.ts +276 -0
  240. package/src/router/revalidation.ts +144 -74
  241. package/src/router/route-snapshot.ts +244 -0
  242. package/src/router/router-context.ts +8 -28
  243. package/src/router/router-interfaces.ts +129 -36
  244. package/src/router/router-options.ts +185 -23
  245. package/src/router/router-registry.ts +2 -5
  246. package/src/router/segment-resolution/fresh.ts +281 -76
  247. package/src/router/segment-resolution/helpers.ts +116 -31
  248. package/src/router/segment-resolution/loader-cache.ts +63 -37
  249. package/src/router/segment-resolution/revalidation.ts +493 -391
  250. package/src/router/segment-resolution/static-store.ts +19 -5
  251. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  252. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  253. package/src/router/segment-resolution.ts +5 -1
  254. package/src/router/segment-wrappers.ts +8 -5
  255. package/src/router/state-cookie-name.ts +33 -0
  256. package/src/router/substitute-pattern-params.ts +56 -0
  257. package/src/router/telemetry-otel.ts +161 -199
  258. package/src/router/telemetry.ts +96 -19
  259. package/src/router/timeout.ts +0 -20
  260. package/src/router/tracing.ts +206 -0
  261. package/src/router/trie-matching.ts +180 -58
  262. package/src/router/types.ts +10 -63
  263. package/src/router/url-params.ts +44 -0
  264. package/src/router.ts +182 -54
  265. package/src/rsc/handler-context.ts +3 -2
  266. package/src/rsc/handler.ts +702 -460
  267. package/src/rsc/helpers.ts +168 -46
  268. package/src/rsc/index.ts +2 -25
  269. package/src/rsc/json-route-result.ts +38 -0
  270. package/src/rsc/loader-fetch.ts +127 -31
  271. package/src/rsc/manifest-init.ts +33 -42
  272. package/src/rsc/origin-guard.ts +39 -25
  273. package/src/rsc/progressive-enhancement.ts +98 -19
  274. package/src/rsc/redirect-guard.ts +99 -0
  275. package/src/rsc/response-cache-serve.ts +238 -0
  276. package/src/rsc/response-error.ts +79 -12
  277. package/src/rsc/response-route-handler.ts +99 -189
  278. package/src/rsc/rsc-rendering.ts +126 -106
  279. package/src/rsc/runtime-warnings.ts +23 -10
  280. package/src/rsc/server-action.ts +269 -114
  281. package/src/rsc/ssr-setup.ts +144 -0
  282. package/src/rsc/types.ts +34 -6
  283. package/src/runtime-env.ts +18 -0
  284. package/src/search-params.ts +49 -41
  285. package/src/segment-content-promise.ts +67 -0
  286. package/src/segment-loader-promise.ts +149 -0
  287. package/src/segment-system.tsx +281 -129
  288. package/src/serialize.ts +243 -0
  289. package/src/server/context.ts +317 -63
  290. package/src/server/cookie-parse.ts +32 -0
  291. package/src/server/cookie-store.ts +80 -5
  292. package/src/server/handle-store.ts +40 -38
  293. package/src/server/loader-registry.ts +26 -46
  294. package/src/server/request-context.ts +425 -177
  295. package/src/server.ts +6 -0
  296. package/src/ssr/index.tsx +25 -16
  297. package/src/static-handler.ts +27 -18
  298. package/src/testing/cache-status.ts +162 -0
  299. package/src/testing/collect-handle.ts +40 -0
  300. package/src/testing/dispatch.ts +701 -0
  301. package/src/testing/dom.entry.ts +22 -0
  302. package/src/testing/e2e/fixture.ts +188 -0
  303. package/src/testing/e2e/index.ts +128 -0
  304. package/src/testing/e2e/matchers.ts +35 -0
  305. package/src/testing/e2e/page-helpers.ts +272 -0
  306. package/src/testing/e2e/parity.ts +387 -0
  307. package/src/testing/e2e/server.ts +195 -0
  308. package/src/testing/flight-matchers.ts +97 -0
  309. package/src/testing/flight-normalize.ts +11 -0
  310. package/src/testing/flight-runtime.d.ts +57 -0
  311. package/src/testing/flight-tree.ts +682 -0
  312. package/src/testing/flight.entry.ts +52 -0
  313. package/src/testing/flight.ts +257 -0
  314. package/src/testing/generated-routes.ts +183 -0
  315. package/src/testing/index.ts +99 -0
  316. package/src/testing/internal/context.ts +371 -0
  317. package/src/testing/internal/flight-client-globals.ts +30 -0
  318. package/src/testing/internal/seed-vars.ts +54 -0
  319. package/src/testing/render-handler.ts +343 -0
  320. package/src/testing/render-route.tsx +581 -0
  321. package/src/testing/run-loader.ts +385 -0
  322. package/src/testing/run-middleware.ts +205 -0
  323. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  324. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  325. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  326. package/src/testing/vitest-stubs/version.ts +5 -0
  327. package/src/testing/vitest.ts +305 -0
  328. package/src/theme/ThemeProvider.tsx +20 -58
  329. package/src/theme/ThemeScript.tsx +7 -9
  330. package/src/theme/constants.ts +52 -13
  331. package/src/theme/index.ts +3 -19
  332. package/src/theme/theme-context.ts +1 -5
  333. package/src/theme/theme-script.ts +22 -21
  334. package/src/theme/use-theme.ts +0 -3
  335. package/src/types/boundaries.ts +0 -35
  336. package/src/types/cache-types.ts +17 -8
  337. package/src/types/error-types.ts +30 -90
  338. package/src/types/global-namespace.ts +54 -41
  339. package/src/types/handler-context.ts +236 -88
  340. package/src/types/index.ts +1 -10
  341. package/src/types/loader-types.ts +44 -15
  342. package/src/types/request-scope.ts +112 -0
  343. package/src/types/route-config.ts +10 -45
  344. package/src/types/route-entry.ts +19 -7
  345. package/src/types/segments.ts +37 -19
  346. package/src/urls/include-helper.ts +33 -70
  347. package/src/urls/index.ts +1 -11
  348. package/src/urls/path-helper-types.ts +58 -11
  349. package/src/urls/path-helper.ts +57 -111
  350. package/src/urls/pattern-types.ts +48 -19
  351. package/src/urls/response-types.ts +25 -22
  352. package/src/urls/type-extraction.ts +58 -139
  353. package/src/urls/urls-function.ts +1 -18
  354. package/src/use-loader.tsx +346 -89
  355. package/src/vite/debug.ts +185 -0
  356. package/src/vite/discovery/bundle-postprocess.ts +64 -91
  357. package/src/vite/discovery/discover-routers.ts +147 -88
  358. package/src/vite/discovery/discovery-errors.ts +194 -0
  359. package/src/vite/discovery/gate-state.ts +171 -0
  360. package/src/vite/discovery/prerender-collection.ts +247 -145
  361. package/src/vite/discovery/route-types-writer.ts +40 -84
  362. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  363. package/src/vite/discovery/state.ts +61 -13
  364. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  365. package/src/vite/index.ts +10 -3
  366. package/src/vite/inject-client-debug.ts +36 -0
  367. package/src/vite/plugin-types.ts +155 -65
  368. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  369. package/src/vite/plugins/client-ref-dedup.ts +120 -0
  370. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  371. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  372. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  373. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  374. package/src/vite/plugins/expose-action-id.ts +49 -98
  375. package/src/vite/plugins/expose-id-utils.ts +96 -51
  376. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  377. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  378. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  379. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  380. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  381. package/src/vite/plugins/performance-tracks.ts +89 -0
  382. package/src/vite/plugins/refresh-cmd.ts +127 -0
  383. package/src/vite/plugins/use-cache-transform.ts +73 -83
  384. package/src/vite/plugins/version-injector.ts +21 -25
  385. package/src/vite/plugins/version-plugin.ts +46 -37
  386. package/src/vite/plugins/virtual-entries.ts +13 -18
  387. package/src/vite/rango.ts +241 -287
  388. package/src/vite/router-discovery.ts +956 -149
  389. package/src/vite/utils/ast-handler-extract.ts +26 -35
  390. package/src/vite/utils/banner.ts +4 -4
  391. package/src/vite/utils/bundle-analysis.ts +10 -15
  392. package/src/vite/utils/client-chunks.ts +184 -0
  393. package/src/vite/utils/directive-prologue.ts +40 -0
  394. package/src/vite/utils/forward-user-plugins.ts +171 -0
  395. package/src/vite/utils/manifest-utils.ts +4 -59
  396. package/src/vite/utils/package-resolution.ts +20 -52
  397. package/src/vite/utils/prerender-utils.ts +141 -34
  398. package/src/vite/utils/shared-utils.ts +92 -42
  399. package/CLAUDE.md +0 -5
  400. package/src/browser/action-response-classifier.ts +0 -99
  401. package/src/browser/react/use-client-cache.ts +0 -58
  402. package/src/browser/shallow.ts +0 -40
  403. package/src/handles/index.ts +0 -6
  404. package/src/network-error-thrower.tsx +0 -23
  405. package/src/route-definition/route-function.ts +0 -119
  406. package/src/router/middleware-cookies.ts +0 -55
package/AGENTS.md ADDED
@@ -0,0 +1,17 @@
1
+ # @rangojs/router
2
+
3
+ A file-system based React Server Components router.
4
+
5
+ Run `/rango` to understand the API. Detailed guides for each feature are in the `skills/` directory (e.g. `node_modules/@rangojs/router/skills/loader`, `skills/caching`, `skills/middleware`, etc.).
6
+
7
+ ## Development rules
8
+
9
+ - Always commit generated files (e.g. `*.gen.ts`) alongside the source changes that produced them.
10
+
11
+ ## Repo-wide rules (read before pushing)
12
+
13
+ This package inherits the repo-wide conventions in the root [`AGENTS.md`](../../AGENTS.md) and [`CLAUDE.md`](../../CLAUDE.md). The ones a package-scoped reader is most likely to miss:
14
+
15
+ - **Pre-push gate** — before EVERY push, run all of the following from the **repo root** and fix any failures: `pnpm run typecheck`, `pnpm run test:unit:all`, `pnpm run lint`, `pnpm run format`.
16
+ - **`test:unit:all` is recursive** — it runs the unit AND Flight/RSC suites for every package and consumer app (cloudflare-basic, mini, vite-rsc-demo, ...), not just `@rangojs/router`. A change can pass this package's own tests while breaking a consumer app's `@rangojs/router/testing` dogfood suite, so do not run only `pnpm --filter @rangojs/router test:unit`.
17
+ - **Dev + prod e2e parity is mandatory** — every e2e test must cover BOTH dev and production modes; never add a dev-only test without its production counterpart. See the dev/prod bucketing convention in the root `AGENTS.md`.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # @rangojs/router
1
+ # Rango
2
2
 
3
- Named-route RSC router with structural composability and type-safe partial rendering for Vite.
3
+ React RSC Route Wrangler
4
+
5
+ A code-first, type-safe React Server Components router
4
6
 
5
7
  > **Experimental:** This package is under active development. APIs may change between releases. Install with `@experimental` tag.
6
8
 
@@ -10,6 +12,7 @@ Named-route RSC router with structural composability and type-safe partial rende
10
12
  - **Structural composability** — Attach routes, loaders, middleware, handles, caching, prerendering, and static generation without hiding the route tree
11
13
  - **Composable URL patterns** — Django-style `urls()` DSL with `path`, `layout`, `include`
12
14
  - **Data loaders** — `createLoader()` with automatic streaming and Suspense integration
15
+ - **Server actions** — `"use server"` mutations with `useActionState`, `useOptimistic`, and per-segment + per-loader `revalidate()` rules
13
16
  - **Live data layer** — Pre-render or cache the UI shell while loaders stay live by default at request time
14
17
  - **Layouts & nesting** — Nested layouts with `<Outlet />` and parallel routes
15
18
  - **Segment-level caching** — `cache()` DSL with TTL/SWR and pluggable cache stores
@@ -45,6 +48,30 @@ For Cloudflare Workers:
45
48
  npm install @cloudflare/vite-plugin
46
49
  ```
47
50
 
51
+ ## Import Paths
52
+
53
+ Use these import paths consistently:
54
+
55
+ - `@rangojs/router` — server/RSC router APIs, route DSL, `createRouter`, `urls`, `redirect`, `Prerender`, `Static`, shared types
56
+ - `@rangojs/router/client` — hooks and components such as `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `useAction`, `useLocationState`
57
+ - `@rangojs/router/cache` — public cache APIs such as `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware`
58
+ - `@rangojs/router/host`, `@rangojs/router/theme`, `@rangojs/router/vite` — specialized public subpaths
59
+ - `@rangojs/router/rsc`, `@rangojs/router/ssr` — advanced server-only integration subpaths for custom request/HTML pipelines
60
+
61
+ Use only subpaths that are explicitly exported from the package. Avoid deep imports such as `@rangojs/router/cache/cf`.
62
+
63
+ `@rangojs/router` is conditionally resolved. Server-only root APIs such as
64
+ `createRouter()`, `urls()`, `redirect()`, `Prerender()`, and `cookies()` rely on
65
+ the `react-server` export condition and are meant to run in router definitions,
66
+ handlers, and other RSC/server modules. Outside that environment the root entry
67
+ falls back to stub implementations that throw guidance errors.
68
+
69
+ If you hit a root-entrypoint stub error:
70
+
71
+ - hooks and components like `Link`, `Outlet`, `useLoader`, `useNavigation`, and `MetaTags` belong in `@rangojs/router/client`
72
+ - cache APIs like `CFCacheStore` and `createDocumentCacheMiddleware` belong in `@rangojs/router/cache`
73
+ - host-router APIs belong in `@rangojs/router/host`
74
+
48
75
  ## Quick Start
49
76
 
50
77
  ### Vite Config
@@ -62,26 +89,34 @@ export default defineConfig({
62
89
 
63
90
  ### Router
64
91
 
92
+ This file is a server/RSC module and should import router construction APIs from
93
+ `@rangojs/router`.
94
+
65
95
  ```tsx
66
96
  // src/router.tsx
67
- import { createRouter, urls } from "@rangojs/router";
68
- import { Document } from "./document";
97
+ import { createRouter } from "@rangojs/router";
69
98
 
70
- const blogPatterns = urls(({ path }) => [
71
- path("/", BlogIndexPage, { name: "index" }),
72
- path("/:slug", BlogPostPage, { name: "post" }),
99
+ export const router = createRouter().routes(({ path }) => [
100
+ path("/", HomePage, { name: "home" }),
101
+ path("/about", AboutPage, { name: "about" }),
73
102
  ]);
74
103
 
104
+ export const reverse = router.reverse;
105
+ // reverse("home") -> "/"
106
+ ```
107
+
108
+ For larger apps, extract route modules with `urls()` and compose with `include()`:
109
+
110
+ ```tsx
111
+ import { createRouter, urls } from "@rangojs/router";
112
+ import { blogPatterns } from "./urls/blog";
113
+
75
114
  const urlpatterns = urls(({ path, include }) => [
76
115
  path("/", HomePage, { name: "home" }),
77
116
  include("/blog", blogPatterns, { name: "blog" }),
78
117
  ]);
79
118
 
80
- export const router = createRouter({ document: Document }).routes(urlpatterns);
81
-
82
- // Export typed reverse function for URL generation by route name
83
- export const reverse = router.reverse;
84
-
119
+ export const router = createRouter().routes(urlpatterns);
85
120
  // reverse("blog.post", { slug: "hello-world" }) -> "/blog/hello-world"
86
121
  ```
87
122
 
@@ -92,20 +127,29 @@ export const reverse = router.reverse;
92
127
  "use client";
93
128
 
94
129
  import type { ReactNode } from "react";
95
- import { MetaTags } from "@rangojs/router/client";
130
+ import { MetaTags, Scripts } from "@rangojs/router/client";
96
131
 
97
132
  export function Document({ children }: { children: ReactNode }) {
98
133
  return (
99
134
  <html lang="en">
100
135
  <head>
101
136
  <MetaTags />
137
+ <Scripts />
102
138
  </head>
103
- <body>{children}</body>
139
+ <body>
140
+ <Scripts position="body" />
141
+ {children}
142
+ </body>
104
143
  </html>
105
144
  );
106
145
  }
107
146
  ```
108
147
 
148
+ `<MetaTags />` and `<Scripts />` render the tags collected by the built-in `Meta`
149
+ and `Script` handles (see [Meta Tags](#meta-tags) and [Scripts](#scripts)). The
150
+ built-in `DefaultDocument` already includes all three sites, so this is only
151
+ needed for a custom document.
152
+
109
153
  ## Defining Routes
110
154
 
111
155
  Rango is a named-route router first.
@@ -129,13 +173,18 @@ const urlpatterns = urls(({ path }) => [
129
173
  ]);
130
174
  ```
131
175
 
132
- Use `reverse()` as the default way to link to routes:
176
+ Use `ctx.reverse()` from handler context as the default way to link to routes from server code:
133
177
 
134
178
  ```tsx
135
- router.reverse("product", { slug: "widget" }); // "/product/widget"
136
- router.reverse("search", undefined, { q: "rsc" }); // "/search?q=rsc"
179
+ const ProductPage: Handler<"product"> = (ctx) => {
180
+ const url = ctx.reverse("product", { slug: "widget" }); // "/product/widget"
181
+ const searchUrl = ctx.reverse("search", undefined, { q: "rsc" }); // "/search?q=rsc"
182
+ return <Link to={url}>Widget</Link>;
183
+ };
137
184
  ```
138
185
 
186
+ `router.reverse()` (exported from the router module) is the same function without a handler context, useful in scripts or tests. In request code, prefer `ctx.reverse()` — it auto-fills mount params from the current match.
187
+
139
188
  ### Composable URL Modules
140
189
 
141
190
  Local route names compose cleanly with `include(..., { name })`:
@@ -248,7 +297,8 @@ All handler typing styles are supported, but they solve different problems:
248
297
  Example of a scoped local name inside a mounted module:
249
298
 
250
299
  ```tsx
251
- import type { Handler, ScopedRouteMap } from "@rangojs/router";
300
+ import type { Handler } from "@rangojs/router";
301
+ import type { ScopedRouteMap } from "@rangojs/router/__internal";
252
302
 
253
303
  type BlogRoutes = ScopedRouteMap<"blog">;
254
304
 
@@ -444,41 +494,130 @@ const urlpatterns = urls(({ path, loader }) => [
444
494
  ]);
445
495
  ```
446
496
 
447
- ## Navigation & Links
497
+ ## Server Actions
498
+
499
+ Server actions are React's RSC mutation primitive. Define them with the
500
+ `"use server"` directive — Rango uses standard React 19 hooks
501
+ (`useActionState`, `useFormStatus`, `useOptimistic`) with no framework wrapper.
502
+
503
+ ```tsx
504
+ // app/actions/cart.ts
505
+ "use server";
448
506
 
449
- ### Named Routes with `reverse()` (Server Components)
507
+ import { getRequestContext } from "@rangojs/router";
450
508
 
451
- In server components, use `reverse()` to generate URLs by route name:
509
+ export async function addToCart(productId: string): Promise<void> {
510
+ const ctx = getRequestContext();
511
+ const userId = ctx.get("user").id;
512
+ await db.cart.insert({ userId, productId });
513
+ }
514
+ ```
452
515
 
453
516
  ```tsx
454
- import { Link } from "@rangojs/router/client";
455
- import { reverse } from "./router";
517
+ // Client form with progressive enhancement + pending state
518
+ "use client";
519
+ import { useActionState } from "react";
520
+ import { saveProfile } from "../actions/profile";
456
521
 
457
- function BlogIndex() {
522
+ export function ProfileForm() {
523
+ const [state, action, pending] = useActionState(saveProfile, null);
458
524
  return (
459
- <nav>
460
- <Link to={reverse("home")}>Home</Link>
461
- <Link to={reverse("blogPost", { slug: "my-post" })}>My Post</Link>
462
- <Link to={reverse("about")}>About</Link>
463
- </nav>
525
+ <form action={action}>
526
+ <input name="name" defaultValue={state?.values?.name} />
527
+ {state?.errors?.name && <p role="alert">{state.errors.name}</p>}
528
+ <button disabled={pending}>{pending ? "Saving…" : "Save"}</button>
529
+ </form>
464
530
  );
465
531
  }
466
532
  ```
467
533
 
468
- `reverse()` is type-safe route names and required params are checked at compile time. Included routes use dotted names: `reverse("api.health")`.
534
+ After an action runs, matched route segments (path/layout/parallel/intercept)
535
+ and loaders can re-render/re-resolve so the UI reflects the new state.
536
+ Attach a `revalidate(({ actionId }) => ...)` rule on any segment or loader
537
+ that owns data the action touched:
469
538
 
470
- Handlers also have `ctx.reverse()` directly on the context:
539
+ ```tsx
540
+ urls(({ path, loader, revalidate }) => [
541
+ // Segment-level: re-render the cart page handler after cart actions.
542
+ // Nest loaders that belong to this route inside the same path() so the
543
+ // segment owns its data dependencies.
544
+ path("/cart", CartPage, { name: "cart" }, () => [
545
+ revalidate(
546
+ ({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
547
+ ),
548
+ loader(CartLoader, () => [
549
+ revalidate(
550
+ ({ actionId }) => actionId?.startsWith("src/actions/cart.ts#") ?? false,
551
+ ),
552
+ ]),
553
+ ]),
554
+ ]);
555
+ ```
556
+
557
+ For the full guide — validation with Zod, error handling, file uploads,
558
+ `useOptimistic`, redirects, and progressive enhancement — see the
559
+ `/server-actions` skill.
560
+
561
+ ## Navigation & Links
562
+
563
+ ### Named Routes with `ctx.reverse()` (Server)
564
+
565
+ In server components and handlers, use `ctx.reverse()` to generate URLs by route name. This is the default — it is typed, auto-fills mount params from the current match, and resolves both local (`.name`) and absolute (`name.sub`) names:
471
566
 
472
567
  ```tsx
568
+ import { Link } from "@rangojs/router/client";
569
+ import type { Handler } from "@rangojs/router";
570
+
473
571
  const BlogPostPage: Handler<"blogPost"> = (ctx) => {
474
572
  const backUrl = ctx.reverse("blog");
475
573
  return <Link to={backUrl}>Back to blog</Link>;
476
574
  };
477
575
  ```
478
576
 
577
+ `reverse()` is type-safe — route names and required params are checked at compile time. Included routes use dotted names: `ctx.reverse("api.health")`.
578
+
579
+ For scripts, tests, or other code without a handler context, import the router-level `reverse`:
580
+
581
+ ```tsx
582
+ import { reverse } from "./router";
583
+ reverse("blogPost", { slug: "my-post" });
584
+ ```
585
+
586
+ ### Client Components
587
+
588
+ **`reverse()` is server-only.** It depends on the route manifest and handler context — neither is available in the browser bundle. Client components receive URLs as props, loader data, or server-action return values:
589
+
590
+ ```tsx
591
+ // server
592
+ function BlogIndex(ctx: HandlerContext) {
593
+ return (
594
+ <Nav
595
+ home={ctx.reverse("home")}
596
+ post={ctx.reverse("blogPost", { slug: "my-post" })}
597
+ />
598
+ );
599
+ }
600
+ ```
601
+
602
+ ```tsx
603
+ "use client";
604
+ import { Link } from "@rangojs/router/client";
605
+
606
+ export function Nav({ home, post }: { home: string; post: string }) {
607
+ return (
608
+ <nav>
609
+ <Link to={home}>Home</Link>
610
+ <Link to={post}>My Post</Link>
611
+ </nav>
612
+ );
613
+ }
614
+ ```
615
+
616
+ For client-side navigation to static paths (no named-route lookup), use `href()` — see below. For URLs tied to named routes, you have two options: import the per-module generated `routes` map and use `useReverse(routes)` for in-module names (see [`/links` skill](./skills/links/SKILL.md)), or generate the URL on the server and pass the string in for cross-module URLs.
617
+
479
618
  ### `href()` for Path Validation (Client Components)
480
619
 
481
- In client components, use `href()` for compile-time path validation:
620
+ In client components, use `href()` for compile-time path validation on static path strings:
482
621
 
483
622
  ```tsx
484
623
  "use client";
@@ -488,7 +627,7 @@ function Nav() {
488
627
  return (
489
628
  <nav>
490
629
  <Link to={href("/")}>Home</Link>
491
- <Link to={href("/blog")} prefetch="hybrid">
630
+ <Link to={href("/blog")} prefetch="adaptive">
492
631
  Blog
493
632
  </Link>
494
633
  <Link to={href("/about")}>About</Link>
@@ -683,10 +822,12 @@ export const BlogPost = Prerender(
683
822
 
684
823
  ### Passthrough for Unknown Params
685
824
 
825
+ Wrap a `Prerender` definition with `Passthrough()` to add a live handler for unknown params at runtime. The build handler runs at build time, the live handler runs at request time for params not in the prerender cache.
826
+
686
827
  ```tsx
687
- import { Prerender } from "@rangojs/router";
828
+ import { Prerender, Passthrough } from "@rangojs/router";
688
829
 
689
- export const ProductPage = Prerender(
830
+ export const ProductPageDef = Prerender(
690
831
  async () => {
691
832
  const featured = await db.getFeaturedProducts();
692
833
  return featured.map((p) => ({ id: p.id }));
@@ -695,16 +836,22 @@ export const ProductPage = Prerender(
695
836
  const product = await db.getProduct(ctx.params.id);
696
837
  return <Product data={product} />;
697
838
  },
698
- { passthrough: true },
699
839
  );
700
- ```
701
840
 
702
- With `passthrough: true`, known params are served from the build-time cache and unknown params fall through to live rendering.
841
+ // In route definition:
842
+ path(
843
+ "/products/:id",
844
+ Passthrough(ProductPageDef, async (ctx) => {
845
+ const product = await ctx.env.DB.getProduct(ctx.params.id);
846
+ return <Product data={product} />;
847
+ }),
848
+ );
849
+ ```
703
850
 
704
- Handlers can also skip individual param sets with `ctx.passthrough()`, deferring them to the live handler at runtime:
851
+ Build handlers can also skip individual param sets with `ctx.passthrough()`, deferring them to the live handler:
705
852
 
706
853
  ```tsx
707
- export const ProductPage = Prerender(
854
+ export const ProductPageDef = Prerender(
708
855
  async () => {
709
856
  const all = await db.getAllProducts();
710
857
  return all.map((p) => ({ id: p.id }));
@@ -714,10 +861,55 @@ export const ProductPage = Prerender(
714
861
  if (!product.published) return ctx.passthrough();
715
862
  return <Product data={product} />;
716
863
  },
717
- { passthrough: true },
718
864
  );
719
865
  ```
720
866
 
867
+ ### Build-Time Environment Bindings
868
+
869
+ Prerender handlers can access platform bindings (KV, D1, R2) at build time when `buildEnv` is configured in the Vite plugin:
870
+
871
+ ```ts
872
+ // vite.config.ts
873
+ import { rango } from "@rangojs/router/vite";
874
+
875
+ rango({ preset: "cloudflare", buildEnv: "auto" });
876
+ ```
877
+
878
+ With `buildEnv: "auto"`, the plugin calls `wrangler.getPlatformProxy()` to provide local bindings. Handlers then access `ctx.env` during build:
879
+
880
+ ```tsx
881
+ export const BlogPosts = Prerender<{ slug: string }>(
882
+ async (ctx) => {
883
+ const rows = await ctx.env.DB.prepare("SELECT slug FROM posts").all();
884
+ return rows.map((r) => ({ slug: r.slug }));
885
+ },
886
+ async (ctx) => {
887
+ const post = await ctx.env.DB.prepare("SELECT * FROM posts WHERE slug = ?")
888
+ .bind(ctx.params.slug)
889
+ .first();
890
+ return <BlogPost post={post} />;
891
+ },
892
+ );
893
+ ```
894
+
895
+ `buildEnv` also accepts a factory function or plain object:
896
+
897
+ ```ts
898
+ // Custom factory
899
+ rango({
900
+ buildEnv: async (ctx) => {
901
+ const { getPlatformProxy } = await import("wrangler");
902
+ const proxy = await getPlatformProxy();
903
+ return { env: proxy.env, dispose: proxy.dispose };
904
+ },
905
+ });
906
+
907
+ // Plain object (Node.js)
908
+ rango({ buildEnv: { DATABASE_URL: process.env.DATABASE_URL } });
909
+ ```
910
+
911
+ Build-time env applies to both production builds and dev on-demand prerender. Without `buildEnv`, accessing `ctx.env` in a Prerender handler throws with a clear error.
912
+
721
913
  ## Theme
722
914
 
723
915
  ### Router Configuration
@@ -762,9 +954,9 @@ import { createHostRouter } from "@rangojs/router/host";
762
954
 
763
955
  const hostRouter = createHostRouter();
764
956
 
765
- hostRouter.host(["*.localhost"]).map(() => import("./apps/admin/handler.js"));
766
- hostRouter.host(["localhost"]).map(() => import("./apps/site/handler.js"));
767
- hostRouter.fallback().map(() => import("./apps/site/handler.js"));
957
+ hostRouter.host(["*.localhost"]).lazy(() => import("./apps/admin/handler.js"));
958
+ hostRouter.host(["localhost"]).lazy(() => import("./apps/site/handler.js"));
959
+ hostRouter.fallback().lazy(() => import("./apps/site/handler.js"));
768
960
 
769
961
  export default {
770
962
  async fetch(request, env, ctx) {
@@ -773,7 +965,7 @@ export default {
773
965
  };
774
966
  ```
775
967
 
776
- Each sub-app has its own `createRouter()` and `urls()`. The host router lazily imports the matched app's handler. Patterns are matched in registration order — register more specific patterns (subdomains) before catch-alls.
968
+ Use `.lazy(() => import("./sub-app"))` to mount a lazily-imported sub-app (a module whose `default` export is a handler or nested host router), and `.map((request) => Response)` for an inline request handler. Only `.lazy()` mounts are imported during build-time discovery; `.map(() => import(...))` is a type error. Each sub-app has its own `createRouter()` and `urls()`. Patterns are matched in registration order — register more specific patterns (subdomains) before catch-alls.
777
969
 
778
970
  ## Meta Tags
779
971
 
@@ -795,6 +987,38 @@ export function BlogPostPage(ctx: HandlerContext) {
795
987
 
796
988
  Render collected tags in the document with `<MetaTags />` from `@rangojs/router/client`.
797
989
 
990
+ ## Scripts
991
+
992
+ Inject `<script>` tags (analytics, GTM, widgets) the same way, using the built-in
993
+ `Script` handle — push a config from a handler, render with `<Scripts />`:
994
+
995
+ ```tsx
996
+ import { Script } from "@rangojs/router";
997
+ import type { HandlerContext } from "@rangojs/router";
998
+ import { Outlet } from "@rangojs/router/client";
999
+
1000
+ export function RootLayout(ctx: HandlerContext) {
1001
+ // Inline bootstrap (GTM/GA4/Segment) — rendered with the request CSP nonce.
1002
+ ctx.use(Script)({ id: "gtm", children: gtmBootstrap("GTM-XXXX") });
1003
+ // External async resource (loads on first encounter, deduped by src).
1004
+ ctx.use(Script)({
1005
+ id: "plausible",
1006
+ src: "https://plausible.io/js/script.js",
1007
+ async: true,
1008
+ attributes: { "data-domain": "example.com" },
1009
+ });
1010
+ return <Outlet />;
1011
+ }
1012
+ ```
1013
+
1014
+ Render with `<Scripts />` (head) and `<Scripts position="body" />` (body) from
1015
+ `@rangojs/router/client` (both are wired in `DefaultDocument`). The request CSP
1016
+ nonce is applied automatically to document-rendered scripts. `ScriptConfig` is a
1017
+ discriminated union (inline / external-async / external-ordered), and inline +
1018
+ ordered scripts are document-load while async externals are React resources — see
1019
+ the [`/scripts` skill](./skills/scripts/SKILL.md) for the full execution contract
1020
+ and CSP guidance.
1021
+
798
1022
  ## CLI: `rango generate`
799
1023
 
800
1024
  Route types are generated automatically by the Vite plugin. The CLI is a manual fallback for generating types outside the dev server (e.g. in CI or for IDE support before first `pnpm dev`):
@@ -812,16 +1036,16 @@ Auto-detects file type:
812
1036
 
813
1037
  ## Type Safety
814
1038
 
815
- The Vite plugin automatically generates a `router.named-routes.gen.ts` file that globally registers route names, patterns, and search schemas via `RSCRouter.GeneratedRouteMap`. This powers server-side named-route typing such as `Handler<"name">`, `ctx.reverse()`, `getRequestContext().reverse()`, and `RouteParams<"name">` without any manual route registration. The gen file is updated on dev server startup, HMR, and production builds.
1039
+ The Vite plugin automatically generates a `router.named-routes.gen.ts` file that globally registers route names, patterns, and search schemas via `Rango.GeneratedRouteMap`. This powers server-side named-route typing such as `Handler<"name">`, `ctx.reverse()`, `getRequestContext().reverse()`, and `RouteParams<"name">` without any manual route registration. The gen file is updated on dev server startup, HMR, and production builds.
816
1040
 
817
- Use the generated map by default. Augment `RSCRouter.RegisteredRoutes` only when you need the richer `typeof router.routeMap` shape globally, especially for response-aware and path-based utilities.
1041
+ Use the generated map by default. Augment `Rango.RegisteredRoutes` only when you need the richer `typeof router.routeMap` shape globally, especially for response-aware and path-based utilities.
818
1042
 
819
1043
  ```typescript
820
1044
  // router.tsx
821
1045
  const router = createRouter<AppBindings>({}).routes(urlpatterns);
822
1046
 
823
1047
  declare global {
824
- namespace RSCRouter {
1048
+ namespace Rango {
825
1049
  interface Env extends AppEnv {}
826
1050
  interface Vars extends AppVars {}
827
1051
  interface RegisteredRoutes extends typeof router.routeMap {}
@@ -833,7 +1057,7 @@ Quick rule of thumb:
833
1057
 
834
1058
  - `GeneratedRouteMap` (auto-generated) — use for server-side named-route typing: `Handler<"name">`, `ctx.reverse()`, `Prerender<"name">`
835
1059
  - `typeof router.routeMap` — use when you need route entries with response metadata
836
- - `RegisteredRoutes` (manual augmentation) — use to expose `typeof router.routeMap` globally for `href()`, `PathResponse`, `ValidPaths`, and other path/response-aware utilities
1060
+ - `RegisteredRoutes` (manual augmentation) — use to expose `typeof router.routeMap` globally for `href()`, `Rango.Path`, `Rango.PathResponse`, and other path/response-aware utilities
837
1061
 
838
1062
  For extracted reusable loaders or middleware, prefer global dotted names on
839
1063
  `ctx.reverse()` by default. If you want type-safe local names for a specific
@@ -842,22 +1066,28 @@ module, use `scopedReverse<typeof localPatterns>(ctx.reverse)` or
842
1066
 
843
1067
  ## Subpath Exports
844
1068
 
845
- | Export | Description |
846
- | ------------------------ | --------------------------------------------------------------------------------- |
847
- | `@rangojs/router` | Core: `createRouter`, `urls`, `createLoader`, `Handler`, `Prerender`, `Meta` |
848
- | `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags` |
849
- | `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware` |
850
- | `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript` |
851
- | `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts` |
852
- | `@rangojs/router/vite` | Vite plugin: `rango()` |
853
- | `@rangojs/router/server` | Server utilities |
854
- | `@rangojs/router/build` | Build utilities |
1069
+ | Export | Description |
1070
+ | ------------------------ | -------------------------------------------------------------------------------------------------------- |
1071
+ | `@rangojs/router` | Server/RSC core and shared types: `createRouter`, `urls`, `createLoader`, `Handler`, `Prerender`, `Meta` |
1072
+ | `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags` |
1073
+ | `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware` |
1074
+ | `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript` |
1075
+ | `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts` |
1076
+ | `@rangojs/router/vite` | Vite plugin: `rango()` |
1077
+ | `@rangojs/router/rsc` | Advanced server pipeline APIs: `createRSCHandler`, request-context access |
1078
+ | `@rangojs/router/ssr` | Advanced SSR bridge APIs: `createSSRHandler` |
1079
+ | `@rangojs/router/server` | Internal build/runtime utilities for advanced integrations |
1080
+ | `@rangojs/router/build` | Build utilities |
1081
+
1082
+ The root entrypoint is not a generic client/runtime barrel. If you need hooks
1083
+ or components, import from `@rangojs/router/client`; if you need cache or host
1084
+ APIs, use their dedicated subpaths.
855
1085
 
856
1086
  ## Examples
857
1087
 
858
- See the `examples/` directory for full working applications:
1088
+ See the example and demo apps for full working applications:
859
1089
 
860
- - [`cloudflare-basic`](../../examples/cloudflare-basic) — Cloudflare Workers with caching, loaders, theme, and pre-rendering
1090
+ - [`cloudflare-basic`](../../tests/cloudflare-basic) — Cloudflare Workers with caching, loaders, theme, and pre-rendering
861
1091
  - [`cloudflare-multi-router`](../../examples/cloudflare-multi-router) — Multi-app host routing
862
1092
 
863
1093
  ## License