@rangojs/router 0.34.0 → 0.35.0

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 (103) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/{chunk-4HHFQSDC.js → chunk-3CQXDX3A.js} +5 -5
  3. package/dist/bin/{client-urls-projection-4Q5EQDAL.js → client-urls-projection-2GBDM5YK.js} +1 -1
  4. package/dist/bin/rango.js +1 -1
  5. package/dist/bin/{runtime-discovery-2ZTYRZ3V.js → runtime-discovery-PA3V3IFQ.js} +2 -2
  6. package/dist/bin/{temp-rsc-server-EUNKRFJD.js → temp-rsc-server-WDXEHDY7.js} +2 -2
  7. package/dist/types/cache/shell-snapshot.d.ts +1 -1
  8. package/dist/types/cache/types.d.ts +1 -1
  9. package/dist/types/client-urls/server-projection.d.ts +1 -1
  10. package/dist/types/client-urls/types.d.ts +6 -6
  11. package/dist/types/decode-loader-results.d.ts +1 -1
  12. package/dist/types/errors.d.ts +3 -3
  13. package/dist/types/handles/meta.d.ts +2 -2
  14. package/dist/types/loader-store.d.ts +20 -8
  15. package/dist/types/outlet-context.d.ts +1 -1
  16. package/dist/types/route-definition/helpers-types.d.ts +5 -5
  17. package/dist/types/router/loader-resolution.d.ts +1 -1
  18. package/dist/types/router/match-context.d.ts +12 -0
  19. package/dist/types/router/navigation-snapshot.d.ts +17 -0
  20. package/dist/types/router/segment-resolution/loader-cache.d.ts +7 -7
  21. package/dist/types/router/types.d.ts +1 -1
  22. package/dist/types/rsc/shell-capture-constants.d.ts +2 -2
  23. package/dist/types/server/context.d.ts +3 -3
  24. package/dist/types/server/request-context.d.ts +1 -1
  25. package/dist/types/ssr/index.d.ts +1 -1
  26. package/dist/types/ssr/ssr-root.d.ts +1 -1
  27. package/dist/types/ssr-suspension-warning.d.ts +1 -1
  28. package/dist/types/types/loader-types.d.ts +19 -19
  29. package/dist/types/types/segments.d.ts +2 -2
  30. package/dist/types/urls/path-helper-types.d.ts +4 -4
  31. package/dist/types/urls/pattern-types.d.ts +1 -1
  32. package/dist/types/vite/plugin-types.d.ts +1 -1
  33. package/dist/vite/index.js +7 -7
  34. package/package.json +1 -1
  35. package/skills/app-structure/e-commerce.md +1 -1
  36. package/skills/breadcrumbs/SKILL.md +5 -5
  37. package/skills/cache-guide/SKILL.md +4 -4
  38. package/skills/caching/SKILL.md +1 -1
  39. package/skills/catalog.json +2 -2
  40. package/skills/client-urls/SKILL.md +20 -20
  41. package/skills/comparison/references/framework-comparison.md +6 -6
  42. package/skills/defer-hydration/SKILL.md +2 -2
  43. package/skills/handler-use/SKILL.md +5 -5
  44. package/skills/hooks/data.md +5 -2
  45. package/skills/hooks/handle-and-actions.md +9 -9
  46. package/skills/loader/SKILL.md +52 -47
  47. package/skills/middleware/SKILL.md +2 -2
  48. package/skills/migrate-nextjs/SKILL.md +10 -10
  49. package/skills/migrate-react-router/SKILL.md +1 -1
  50. package/skills/migrate-react-router/component-migration.md +2 -2
  51. package/skills/migrate-react-router/data-and-actions.md +2 -2
  52. package/skills/migrate-react-router/route-mapping.md +2 -2
  53. package/skills/parallel/SKILL.md +2 -2
  54. package/skills/ppr/SKILL.md +91 -92
  55. package/skills/prerender/SKILL.md +5 -5
  56. package/skills/rango/SKILL.md +7 -7
  57. package/skills/route/SKILL.md +1 -1
  58. package/skills/router-setup/SKILL.md +2 -2
  59. package/skills/scripts/SKILL.md +3 -3
  60. package/skills/shell-manifest/SKILL.md +3 -3
  61. package/skills/testing/serve-shell-request.md +1 -1
  62. package/skills/theme/SKILL.md +2 -2
  63. package/skills/typesafety/env-and-bindings.md +2 -2
  64. package/skills/use-cache/SKILL.md +1 -1
  65. package/skills/ux-architecture/SKILL.md +7 -7
  66. package/src/cache/shell-snapshot.ts +1 -1
  67. package/src/cache/types.ts +1 -1
  68. package/src/client-urls/client-urls.ts +16 -9
  69. package/src/client-urls/server-projection.ts +4 -4
  70. package/src/client-urls/types.ts +6 -6
  71. package/src/decode-loader-results.ts +1 -1
  72. package/src/errors.ts +9 -9
  73. package/src/handles/meta.ts +2 -2
  74. package/src/loader-store.ts +29 -13
  75. package/src/outlet-context.ts +1 -1
  76. package/src/route-definition/dsl-helpers.ts +4 -8
  77. package/src/route-definition/helpers-types.ts +5 -5
  78. package/src/router/loader-resolution.ts +4 -4
  79. package/src/router/match-api.ts +2 -0
  80. package/src/router/match-context.ts +22 -1
  81. package/src/router/match-middleware/cache-lookup.ts +17 -8
  82. package/src/router/match-middleware/intercept-resolution.ts +3 -3
  83. package/src/router/navigation-snapshot.ts +39 -8
  84. package/src/router/segment-resolution/loader-cache.ts +8 -8
  85. package/src/router/segment-resolution/prefetch-deferral.ts +1 -1
  86. package/src/router/segment-resolution/revalidation.ts +3 -3
  87. package/src/router/types.ts +1 -1
  88. package/src/rsc/shell-capture-constants.ts +3 -3
  89. package/src/rsc/shell-capture.ts +12 -12
  90. package/src/segment-system.tsx +3 -3
  91. package/src/server/context.ts +5 -5
  92. package/src/server/cookie-store.ts +1 -1
  93. package/src/server/request-context.ts +1 -1
  94. package/src/ssr/index.tsx +6 -6
  95. package/src/ssr/ssr-root.tsx +1 -1
  96. package/src/ssr-suspension-warning.ts +4 -4
  97. package/src/types/loader-types.ts +19 -19
  98. package/src/types/segments.ts +2 -2
  99. package/src/urls/path-helper-types.ts +4 -4
  100. package/src/urls/pattern-types.ts +1 -1
  101. package/src/use-loader.tsx +5 -3
  102. package/src/vite/discovery/shell-prerender-phase.ts +1 -1
  103. package/src/vite/plugin-types.ts +1 -1
@@ -10,7 +10,7 @@ Caches the rendered HTML **shell** of a page route (React `prerender` prelude
10
10
  bytes plus `postponed` state) and, on a later request, flushes those bytes after
11
11
  route classification and the complete middleware chain, but before downstream
12
12
  tail rendering. It then resumes React's HTML renderer for just the live holes.
13
- The browser sees one ordinary streamed document; live loaders (no `ssr: false`)
13
+ The browser sees one ordinary streamed document; live loaders (no `ssr: "await"`)
14
14
  stay fresh on every request. A normal render (no shell) is untouched, and every
15
15
  request the shell cannot serve falls open to it.
16
16
 
@@ -38,7 +38,7 @@ PPR with HTTP shared-cache headers.
38
38
  - You want build-time Flight segment payloads from `Static()`/`Prerender()` —
39
39
  see `/prerender`. A `Prerender` page may also declare `ppr`; then the
40
40
  build-time shell capture bakes the HTML shell while loaders without
41
- `ssr: false` stay live.
41
+ `ssr: "await"` stay live.
42
42
  - You want cached segments with live loaders but no cached HTML — that is the
43
43
  `cache()` DSL: see `/caching`.
44
44
  - You are unsure which cache layer you need — start at `/cache-guide`.
@@ -119,9 +119,9 @@ settled by then stores no shell (the once-per-key warning names the cause: "did
119
119
  not settle within ppr.captureTimeout"). A shell HIT never runs a handler: it
120
120
  replays the handler layer the capture recorded.
121
121
 
122
- To keep a region fresh per request, load it in a loader WITHOUT `ssr: false`
122
+ To keep a region fresh per request, load it in a loader WITHOUT `ssr: "await"`
123
123
  and read it with `useLoader` under `loading()` or an inline `<Suspense>` (a live
124
- hole, see "The hole doctrine"); inside a `loader(Def, { ssr: false })`, return
124
+ hole, see "The hole doctrine"); inside a `loader(Def, { ssr: "await" })`, return
125
125
  the live part as a nested promise.
126
126
 
127
127
  A route WITHOUT the `ppr` option renders normally (no shell): no store read, no
@@ -138,8 +138,8 @@ promise it passes to a component under `<Suspense>`, an async server component,
138
138
  a nested promise in a handle it pushes, and a loader it awaits are all awaited
139
139
  at capture (bounded by `ppr.captureTimeout`) and served frozen for the shell's
140
140
  lifetime. A HIT never runs a handler. To keep a value fresh per request, load
141
- it in a loader without `ssr: false` and read it with `useLoader` under
142
- `loading()` or an inline `<Suspense>`; inside an `ssr: false` loader, return
141
+ it in a loader without `ssr: "await"` and read it with `useLoader` under
142
+ `loading()` or an inline `<Suspense>`; inside an `ssr: "await"` loader, return
143
143
  that part as a nested promise. Request-scoped reads the capture now waits for
144
144
  refuse it: `cookies()`, `headers()`, `ctx.request.headers`, a
145
145
  `{ cache: false }` variable, and
@@ -356,7 +356,7 @@ slow leaves the entry alone.
356
356
  ### Soft navigation caches and reuses the handler layer
357
357
 
358
358
  In short: client-side (soft) navigations to a `ppr` route reuse the handler
359
- segments captured with the shell, while loaders without `ssr: false` stay live.
359
+ segments captured with the shell, while loaders without `ssr: "await"` stay live.
360
360
  Nothing needs configuring; the rest of this section explains the
361
361
  `x-rango-ppr-replay` header for when you are debugging replay behavior.
362
362
 
@@ -380,12 +380,12 @@ This is deliberately invisible to the browser: the response is the same
380
380
  `RscPayload` shape as any other partial navigation. A shell snapshot holds no
381
381
  `"use cache"` or loader `cache()` values. Bake-lane loader pins are, when the replayed
382
382
  snapshot is a shell a document request captured, as on a document HIT: a
383
- promise-free `ssr: false` loader is served from its pin without running
383
+ promise-free `ssr: "await"` loader is served from its pin without running
384
384
  (unless the capture marked it to run: see "On a shell HIT"), and one whose
385
385
  return holds promises runs with its baked parts overlaid. A snapshot captured
386
386
  by a navigation alone carries no pins, nor does an entry over
387
387
  `ppr.maxSnapshotBytes`, and its replay runs them fresh. Loaders without
388
- `ssr: false` stay live.
388
+ `ssr: "await"` stay live.
389
389
 
390
390
  A route's own `cache()` scope — including one inherited from an ancestor, the
391
391
  common app-wide storefront shape — COMPOSES with replay instead of disabling
@@ -615,7 +615,7 @@ curl -s -D - -o /dev/null https://app.example.com/products/1 | grep -i x-rango-s
615
615
  the stored entry's size. In dev, past 2s, the settle is also
616
616
  named once per key in a console warning with the remedies (`cache()` the
617
617
  work / move it into a live loader / return it as a nested promise or drop
618
- `ssr: false` in a bake-lane loader). In dev, with
618
+ `ssr: "await"` in a bake-lane loader). In dev, with
619
619
  `debugPerformance` on, the last capture outcome for a key also rides the
620
620
  next document GET's `Server-Timing` as `ppr-capture;desc="…"`.
621
621
  - For deployed Cloudflare tier diagnostics, build with
@@ -682,10 +682,10 @@ skill → `serve-shell-request.md` and `cache-prerender.md` (PPR shell section).
682
682
  Holes are **render-defined**, decided by the shape of the tree. There are two
683
683
  classes, and the handler layer is always on the SHELL side:
684
684
 
685
- | Class | What decides it | At capture | At serve (HIT) |
686
- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
687
- | **STRUCTURAL** | a LIVE-lane loader (no `ssr: false`) read under a boundary: `loading()` (the whole segment subtree under it) or an inline `<Suspense>` above the reader | live loaders masked; the boundary postpones; its fallback bakes in as route structure | loaders run fresh; resume fills the hole |
688
- | **SHELL** | everything the handler layer produces — awaited data, a promise it passes as a prop (even under the consumer's `<Suspense>`), an async server component, handle pushes at any depth, a loader it awaits (`await ctx.use(Loader)`) — plus replayed `cache()` segments and the settled non-promise data of BAKE-lane (`ssr: false`) loaders | awaited (one deadline, `ppr.captureTimeout`) and baked into the prelude and the shell's recorded segments | served from the frozen prelude; no handler runs |
685
+ | Class | What decides it | At capture | At serve (HIT) |
686
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
687
+ | **STRUCTURAL** | a LIVE-lane loader (no `ssr: "await"`) read under a boundary: `loading()` (the whole segment subtree under it) or an inline `<Suspense>` above the reader | live loaders masked; the boundary postpones; its fallback bakes in as route structure | loaders run fresh; resume fills the hole |
688
+ | **SHELL** | everything the handler layer produces — awaited data, a promise it passes as a prop (even under the consumer's `<Suspense>`), an async server component, handle pushes at any depth, a loader it awaits (`await ctx.use(Loader)`) — plus replayed `cache()` segments and the settled non-promise data of BAKE-lane (`ssr: "await"`) loaders | awaited (one deadline, `ppr.captureTimeout`) and baked into the prelude and the shell's recorded segments | served from the frozen prelude; no handler runs |
689
689
 
690
690
  One hole lives INSIDE loader data, decided by shape: a promise nested in a
691
691
  bake-lane loader's return value, or in a handle container a loader pushes, is
@@ -696,13 +696,12 @@ HIT").
696
696
 
697
697
  The promise rule, by producer: **a promise a handler produces bakes, at any
698
698
  depth; a promise nested in loader data stays live.** A
699
- `loader(Def, { ssr: false })` is the BAKE lane (see the lane rule below): its
699
+ `loader(Def, { ssr: "await" })` is the BAKE lane (see the lane rule below): its
700
700
  settled non-promise data is shell material, exactly like handler output, while
701
701
  its nested promises are holes. A live-lane loader is a hole as a whole.
702
- `ssr: false` on a loader is the same knob as `loading(fallback, { ssr: false })`:
703
- the document does not stream a fallback for it but resolves the loader before
704
- the first flush, so under `ppr` its value lands in the prelude and bakes into
705
- the shell. Delivery details: `/loader` → "`ssr: false` — Guarantee a Loader in
702
+ `ssr: "await"` on a loader makes the render await it: the document does not
703
+ stream a fallback for it but resolves the loader before the first flush, so
704
+ under `ppr` its value lands in the prelude and bakes into the shell. Delivery details: `/loader` → "`ssr: "await"` — Guarantee a Loader in
706
705
  the Document".
707
706
 
708
707
  An async server component that never settles inside `ppr.captureTimeout`
@@ -712,7 +711,7 @@ its data into a live loader read under a boundary.
712
711
 
713
712
  ### The loader lane rule
714
713
 
715
- **Only `loader(Def, { ssr: false })` bakes into the shell, and only the parts
714
+ **Only `loader(Def, { ssr: "await" })` bakes into the shell, and only the parts
716
715
  of its returned data that are NOT promises.** The loader runs at capture; its
717
716
  settled non-promise values are frozen into the shell (snapshot-pinned per
718
717
  shell). Any promise inside the returned data is masked at capture and stays a
@@ -749,7 +748,7 @@ registered read stays a live hole.)
749
748
  `ctx.use(Handle)({ ..., x: promise })` inside a loader keeps `x` live. The
750
749
  same push from a HANDLER bakes `x` (see "Handles").
751
750
 
752
- **Every loader without `ssr: false` is entirely live**, whether or not it has
751
+ **Every loader without `ssr: "await"` is entirely live**, whether or not it has
753
752
  `loading()`: masked at capture with a never-resolving promise, postponed at its
754
753
  boundary, and streamed fresh on every request. It needs a boundary —
755
754
  `loading()` or an inline `<Suspense>` above the reader — or the shell is
@@ -758,7 +757,7 @@ sanity gate refuses the capture, and the route stays an eternal MISS (warned
758
757
  once per key). When that read also throws on the MISS render, the document is
759
758
  the 500 recovery document the `/loader` skill describes ("A read outside any
760
759
  `<Suspense>`"), and nothing is stored. A route whose loaders are ALL
761
- `ssr: false` needs no `loading()`: nothing masks, and the shell captures
760
+ `ssr: "await"` needs no `loading()`: nothing masks, and the shell captures
762
761
  complete.
763
762
 
764
763
  ```typescript
@@ -772,7 +771,7 @@ export const ProductLoader = createLoader(async (ctx) => {
772
771
  });
773
772
 
774
773
  path("/products/:id", ProductPage, { name: "product", ppr: true }, () => [
775
- loader(ProductLoader, { ssr: false }), // BAKE lane
774
+ loader(ProductLoader, { ssr: "await" }), // BAKE lane
776
775
  loader(StockLoader), // LIVE lane: ProductPage reads it under an inline <Suspense>
777
776
  ]);
778
777
  ```
@@ -834,7 +833,7 @@ async function Handler(ctx: HandlerContext) {
834
833
  <Suspense>: awaited at capture → BAKED */}
835
834
  <LiveStats /> {/* "use client": useLoader(StatsLoader)
836
835
  under <Suspense>, StatsLoader registered
837
- without ssr: false → HOLE */}
836
+ without ssr: "await" → HOLE */}
838
837
  </section>
839
838
  );
840
839
  }
@@ -845,10 +844,10 @@ async function Handler(ctx: HandlerContext) {
845
844
  | Your live region is… | Use | Why |
846
845
  | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
847
846
  | data that must be fresh EVERY serve | `loader()` (the live lane) + `useLoader` under `loading()` or an inline `<Suspense>` | the guaranteed hole — masked at capture, fresh every serve, immune to fast resolution |
848
- | loader data, shell container + live parts | `loader(Def, { ssr: false })` (the bake lane): `{ static, dynamic: promise }` | plain values bake (snapshot-pinned per shell); nested promises hole at the consumer's `<Suspense>` |
847
+ | loader data, shell container + live parts | `loader(Def, { ssr: "await" })` (the bake lane): `{ static, dynamic: promise }` | plain values bake (snapshot-pinned per shell); nested promises hole at the consumer's `<Suspense>` |
849
848
  | handler-fetched data (db, fetch) | nothing to choose: it bakes, whether the handler awaits it or passes the promise down | handler output is shell material; move the fetch into a live-lane loader to make it live |
850
849
  | handle metadata that must be live | push it from a loader: a live-lane loader pushes per request; a bake-lane loader's nested promise stays a hole | handler pushes bake at any depth; loader pushes keep "nesting = liveness" |
851
- | already-resolved / instant / synchronous values | `loader(() => Promise.resolve(x))` (no `ssr: false`) + a boundary | live-lane loaders are masked at capture no matter how fast they settle |
850
+ | already-resolved / instant / synchronous values | `loader(() => Promise.resolve(x))` (no `ssr: "await"`) + a boundary | live-lane loaders are masked at capture no matter how fast they settle |
852
851
  | none of the above | nothing | it bakes — that is what the shell is for |
853
852
 
854
853
  Why a handler promise cannot be a hole: every HIT replays the handler layer the
@@ -868,11 +867,11 @@ identifiers — served to anonymous visitors.)
868
867
  - `ctx.use(H)(promise)` from a handler — a TOP-LEVEL pushed promise is awaited
869
868
  at capture and BAKED into the shell (bounded by `ppr.captureTimeout`, 15s by
870
869
  default).
871
- - `ctx.use(H)(promise)` (or `.defer()`) from an `ssr: false` LOADER, or a
870
+ - `ctx.use(H)(promise)` (or `.defer()`) from an `ssr: "await"` LOADER, or a
872
871
  loader it awaits — awaited at capture and BAKED the same way, judged by the
873
872
  value it settles to, as `push(await promise)` would be (#1182). One that
874
873
  rejects, or does not settle within `ppr.captureTimeout`, refuses the
875
- capture, as a handler's does. A loader without `ssr: false` never runs at
874
+ capture, as a handler's does. A loader without `ssr: "await"` never runs at
876
875
  capture, so its pushes are never in the shell.
877
876
  - `ctx.use(H)({ x: promise })` from a HANDLER — also baked. The capture waits
878
877
  for every promise nested in a handler's push, at any depth of plain objects,
@@ -881,24 +880,24 @@ identifiers — served to anonymous visitors.)
881
880
  or class instance is not waited for, and if it has not settled when the handles are encoded the
882
881
  capture is refused.
883
882
  - `ctx.use(H)({ x: promise })` from a LOADER — nesting = liveness. A bake-lane
884
- (`ssr: false`) loader's container settles and bakes, while the nested promise
883
+ (`ssr: "await"`) loader's container settles and bakes, while the nested promise
885
884
  is masked at capture regardless of settle timing and streams fresh to the
886
885
  consumer's `<Suspense>` on every HIT (the same mask as bake-lane loader data,
887
886
  at any depth of plain objects, arrays and JSX props; a promise inside a
888
887
  `Map`, `Set`, or class instance is not masked). A live-lane
889
- loader never runs at capture unless a handler or an `ssr: false` loader
888
+ loader never runs at capture unless a handler or an `ssr: "await"` loader
890
889
  awaits it; either
891
890
  way its pushes, and those of the loaders it awaits, are live on every HIT.
892
891
 
893
892
  ### Want a hole for already-resolved data?
894
893
 
895
- Put it in a loader without `ssr: false`: `loader(() => Promise.resolve(x))`
894
+ Put it in a loader without `ssr: "await"`: `loader(() => Promise.resolve(x))`
896
895
  under `loading()` or an inline `<Suspense>`. Live-lane loaders are masked at
897
896
  capture and fresh on every serve, no matter how fast the value settles.
898
897
 
899
- ### The bake lane: `loader(Def, { ssr: false })`
898
+ ### The bake lane: `loader(Def, { ssr: "await" })`
900
899
 
901
- A loader registered with `{ ssr: false }` EXECUTES during capture (the capture
900
+ A loader registered with `{ ssr: "await" }` EXECUTES during capture (the capture
902
901
  gate holds open for its real latency, bounded by `ppr.captureTimeout`, 15s by
903
902
  default). The flag's document promise — "this loader's data is in the HTML
904
903
  before first flush" — maps to the frozen prelude under ppr. Its settled
@@ -920,12 +919,12 @@ export const StorefrontContextLoader = createLoader(async (ctx) => {
920
919
  });
921
920
 
922
921
  layout(StoreLayout, () => [
923
- loader(StorefrontContextLoader, { ssr: false }), // the flag selects the bake lane
922
+ loader(StorefrontContextLoader, { ssr: "await" }), // the flag selects the bake lane
924
923
  path("/", HomePage, { name: "home", ppr: true }),
925
924
  ]);
926
925
  ```
927
926
 
928
- The lane is decided PER LOADER, by its own `ssr: false` flag — `loading()` on
927
+ The lane is decided PER LOADER, by its own `ssr: "await"` flag — `loading()` on
929
928
  the same entry, a parent, or a child never changes it. `loading()` only decides
930
929
  where a live loader's hole sits, and it IS valid on layout and parallel
931
930
  entries, not just routes.
@@ -935,7 +934,7 @@ entries, not just routes.
935
934
  What a bake-lane loader does on a HIT depends on whether its recorded
936
935
  container carried holes. A client navigation that replays a shell captured by
937
936
  a document request (`x-rango-ppr-replay: HIT`) does the same, for every
938
- `ssr: false` loader, including one on an entry with `loading()` (before, a
937
+ `ssr: "await"` loader, including one on an entry with `loading()` (before, a
939
938
  navigation ran every loader and served its fresh values). A snapshot captured
940
939
  by a navigation alone carries no pins, and its replay runs these loaders fresh.
941
940
 
@@ -955,7 +954,7 @@ by a navigation alone carries no pins, and its replay runs these loaders fresh.
955
954
  a document HIT the payload then carries the error where the HTML has the
956
955
  baked value, and React renders that part again on the client (one
957
956
  hydration mismatch, the one known residual of a HIT). Give it its own cache,
958
- `loader(Def, { ssr: false }, () => [cache({ ttl })])`, so that run reads
957
+ `loader(Def, { ssr: "await" }, () => [cache({ ttl })])`, so that run reads
959
958
  through the loader cache.
960
959
 
961
960
  Whether a return "has promises" is decided ONCE, at capture, by the shape of
@@ -972,20 +971,20 @@ its settled value, and a HIT serves that value without running the loader.
972
971
  The granularity is the WHOLE loader: a bake-lane loader returning
973
972
  `{ product, reviews: promise }` runs its entire body on every HIT, the product
974
973
  fetch included, even though the captured product overlays its result. Split
975
- it into a promise-free `ssr: false` loader plus a live loader for the
974
+ it into a promise-free `ssr: "await"` loader plus a live loader for the
976
975
  per-request part, or give it its own `cache()` so that run reads through it:
977
976
 
978
977
  ```tsx
979
- loader(ProductLoader, { ssr: false }), // promise-free: baked, not run on a HIT
978
+ loader(ProductLoader, { ssr: "await" }), // promise-free: baked, not run on a HIT
980
979
  loader(ReviewsLoader), // live: the hole, under loading()
981
980
  ```
982
981
 
983
982
  **A hole never reads the shell's copy of a value.** The shell stores its
984
- recorded segments and the `ssr: false` loaders' baked containers, and no
983
+ recorded segments and the `ssr: "await"` loaders' baked containers, and no
985
984
  `"use cache"` or loader `cache()` value. Every cache read on a HIT goes to
986
985
  the store: a live loader's, a nested promise's, and the body of an
987
- `ssr: false` loader that runs on the HIT. So a live loader that reads the
988
- same `"use cache"` key as an `ssr: false` loader shows the store's current
986
+ `ssr: "await"` loader that runs on the HIT. So a live loader that reads the
987
+ same `"use cache"` key as an `ssr: "await"` loader shows the store's current
989
988
  value once it refreshes, while the baked container keeps the capture's. If a
990
989
  hole needs a stable value, give it its own cache (`"use cache"` with a
991
990
  profile, or a loader `cache()`); the shell never provides one.
@@ -995,7 +994,7 @@ data.** A loader's title, meta or breadcrumb describes the data next to it,
995
994
  so both come from the same run on every way a shell can be replayed: a
996
995
  document HIT, a client navigation, a prefetch. The capture records the
997
996
  settled, thenable-free handle pushes of every loader body it runs (the
998
- prelude rendered them): the `ssr: false` loader's own, those of the loaders
997
+ prelude rendered them): the `ssr: "await"` loader's own, those of the loaders
999
998
  it awaits with `ctx.use()`, and those its own `cache()` entry replays. What
1000
999
  a replay does with a loader's recorded pushes follows what it does with that
1001
1000
  loader's data:
@@ -1014,12 +1013,12 @@ of the loaders it awaits, so they show its live value, even when a bake-lane
1014
1013
  loader running on the replay awaits it. On a document HIT the page hydrates
1015
1014
  with the shell's copy and the hole's value takes its place after hydration
1016
1015
  ("Handles on a shell HIT" below). An
1017
- `ssr: false` loader is served from the shell only while the entry holds its
1016
+ `ssr: "await"` loader is served from the shell only while the entry holds its
1018
1017
  pin: a snapshot captured by a navigation alone carries none, and a capture
1019
1018
  over `ppr.maxSnapshotBytes` stores the navigation half only, without them.
1020
1019
  There a navigation runs the loader fresh, and its pushes are that run's, like
1021
1020
  its data. A document HIT is served only from an entry that holds a pin for
1022
- every `ssr: false` loader its HTML baked, so a document never hydrates one
1021
+ every `ssr: "await"` loader its HTML baked, so a document never hydrates one
1023
1022
  loader's run over HTML rendered from the capture's value.
1024
1023
 
1025
1024
  A `Prerender` + `ppr` page follows the same table. Its handler layer comes
@@ -1027,7 +1026,7 @@ from the prerendered payload, which never holds a loader push (loaders do not
1027
1026
  run at build), so the shell entry records the loader pushes its HTML rendered
1028
1027
  on its own, and a HIT restores them as above (#1057).
1029
1028
 
1030
- A dependency the route does not register, which an `ssr: false` loader
1029
+ A dependency the route does not register, which an `ssr: "await"` loader
1031
1030
  awaited at capture outside any live loader, is on neither lane: its settled
1032
1031
  pushes stay as the prelude rendered them, even where a live loader also
1033
1032
  awaits it, while its data is fresh. (They follow the run instead when the
@@ -1041,7 +1040,7 @@ own `cache()` entry when it hits) with the run's value, on a document HIT and
1041
1040
  on a client navigation alike. On a document HIT it arrives after hydration.
1042
1041
 
1043
1042
  **Handles on a shell HIT.** The shell holds what its capture's document
1044
- rendered: the handlers' pushes and the `ssr: false` loaders' pushes, a
1043
+ rendered: the handlers' pushes and the `ssr: "await"` loaders' pushes, a
1045
1044
  promise (`push(promise)`, `.defer()`) resolved. A pushed promise is judged by
1046
1045
  the value it settles to, as `push(await promise)` would be (#1182). A
1047
1046
  live-lane loader's push is never in a shell.
@@ -1049,10 +1048,10 @@ live-lane loader's push is never in a shell.
1049
1048
  Four things follow, in this order of scope:
1050
1049
 
1051
1050
  1. **What is in a shell's HTML.** The capture awaits a promise an
1052
- `ssr: false` loader (or a loader it awaits) pushes, under
1051
+ `ssr: "await"` loader (or a loader it awaits) pushes, under
1053
1052
  `ppr.captureTimeout`, and bakes the value. One that settles to a value
1054
1053
  holding a promise is live: the shell renders no element for it. A loader
1055
- without `ssr: false` never runs at capture, so nothing of it is ever in
1054
+ without `ssr: "await"` never runs at capture, so nothing of it is ever in
1056
1055
  the shell.
1057
1056
  2. **A pushed promise that fails refuses the capture.** One that rejects, or
1058
1057
  does not settle within `ppr.captureTimeout`, keeps the route on MISS, as
@@ -1069,16 +1068,16 @@ Four things follow, in this order of scope:
1069
1068
  inside the `loading()` or `<Suspense>` of a loader that pushes after an
1070
1069
  `await` hydrates clean.
1071
1070
 
1072
- | On the HIT's request | In the HIT's HTML | The client |
1073
- | ------------------------------------------------------------------------------------------ | ---------------------- | ----------------------------- |
1074
- | a handler's push, a pinned `ssr: false` loader's push (`push(promise)` and `.defer()` too) | yes (the shell has it) | hydrates with it |
1075
- | a push by an `ssr: false` loader whose value holds a promise | no | gets it right after hydration |
1076
- | a live-lane loader's push | no | gets it right after hydration |
1071
+ | On the HIT's request | In the HIT's HTML | The client |
1072
+ | -------------------------------------------------------------------------------------------- | ---------------------- | ----------------------------- |
1073
+ | a handler's push, a pinned `ssr: "await"` loader's push (`push(promise)` and `.defer()` too) | yes (the shell has it) | hydrates with it |
1074
+ | a push by an `ssr: "await"` loader whose value holds a promise | no | gets it right after hydration |
1075
+ | a live-lane loader's push | no | gets it right after hydration |
1077
1076
 
1078
- So a title an `ssr: false` loader pushes to `Meta`, promise or not, is in
1077
+ So a title an `ssr: "await"` loader pushes to `Meta`, promise or not, is in
1079
1078
  every HIT's `<head>`: a crawler and a link preview see it. It bakes with the
1080
1079
  shell and is invalidated with it (its TTL, its tags, `updateTag()`). A value
1081
- that must stay per request comes from a loader without `ssr: false`, which
1080
+ that must stay per request comes from a loader without `ssr: "await"`, which
1082
1081
  nothing has to read:
1083
1082
 
1084
1083
  ```ts
@@ -1087,7 +1086,7 @@ const StockNote = createLoader(async (ctx) => {
1087
1086
  return null;
1088
1087
  });
1089
1088
  path("/product/:id", ProductPage, { name: "product", ppr: true }, () => [
1090
- loader(Product, { ssr: false }), // bakes: its data and its pushes
1089
+ loader(Product, { ssr: "await" }), // bakes: its data and its pushes
1091
1090
  loader(StockNote), // live lane: runs on every request
1092
1091
  ]);
1093
1092
  ```
@@ -1128,8 +1127,8 @@ Four hard edges (each e2e/unit-pinned):
1128
1127
  - **Identity refuses.** `cookies()`/`headers()`/`ctx.request.headers` inside a bake-lane loader
1129
1128
  throws during capture and the capture REFUSES (deterministic, once-per-key
1130
1129
  warned) — identity can never bake into the shared shell. Drop the loader's
1131
- `ssr: false` flag (the live lane is exempt; give it a boundary) or move the
1132
- identity-dependent part into a separate loader without `ssr: false`. A
1130
+ `ssr: "await"` flag (the live lane is exempt; give it a boundary) or move the
1131
+ identity-dependent part into a separate loader without `ssr: "await"`. A
1133
1132
  nested promise does not help here: its body still runs during capture and
1134
1133
  trips the guard. The same refusal covers everything else the capture waits
1135
1134
  for (a handler, a promise it passes or pushes, an async server component, a
@@ -1155,7 +1154,7 @@ Four hard edges (each e2e/unit-pinned):
1155
1154
  document GETs, and on soft navigations that replay a shell captured by a
1156
1155
  document request (`x-rango-ppr-replay: HIT`). Live loaders and their
1157
1156
  `"use cache"` reads remain fresh. That IS the bake lane's meaning; if a value
1158
- must be fresh on every serve, it belongs on the live lane (no `ssr: false`) or
1157
+ must be fresh on every serve, it belongs on the live lane (no `ssr: "await"`) or
1159
1158
  in a nested promise.
1160
1159
 
1161
1160
  ### `prefetch: false` on a `ppr` route
@@ -1167,11 +1166,11 @@ the fallback are deferred. A live loader registered with `{ prefetch: false }` i
1167
1166
  skipped the same way, and the click that adopts the prefetch sends one fill
1168
1167
  request for it.
1169
1168
 
1170
- An `ssr: false` loader (the bake lane) registered with `{ prefetch: false }`
1169
+ An `ssr: "await"` loader (the bake lane) registered with `{ prefetch: false }`
1171
1170
  is deferred too, unless the prefetch serves it from a pin of a shell a
1172
1171
  document request captured:
1173
1172
 
1174
- | The prefetch | The flagged `ssr: false` loader |
1173
+ | The prefetch | The flagged `ssr: "await"` loader |
1175
1174
  | ------------------------------------------------------ | --------------------------------------------------------------------- |
1176
1175
  | Replays a shell a document request captured (`HIT`) | Served from its pin, not deferred, never run; the click sends nothing |
1177
1176
  | Replays a navigation-only shell, or misses (cold page) | Deferred: the click sends one fill that runs it |
@@ -1195,7 +1194,7 @@ refuses and the page stays an eternal MISS. The question is which parts of
1195
1194
  their data should bake vs stay live. Your levers, in order of preference:
1196
1195
 
1197
1196
  1. **Flag the loader and shape the return value.**
1198
- `loader(SessionContextLoader, { ssr: false })` puts it on the bake lane:
1197
+ `loader(SessionContextLoader, { ssr: "await" })` puts it on the bake lane:
1199
1198
  shared/config data returns as plain values (bakes, pinned per shell);
1200
1199
  per-request data returns as NESTED promises consumed under the widget's own
1201
1200
  `<Suspense>` (live holes). No `loading()`, no restructuring. One wall: a
@@ -1238,7 +1237,7 @@ their data should bake vs stay live. Your levers, in order of preference:
1238
1237
  ]),
1239
1238
  ```
1240
1239
 
1241
- Slot-owned loaders without `ssr: false` are masked at capture and
1240
+ Slot-owned loaders without `ssr: "await"` are masked at capture and
1242
1241
  GUARANTEED fresh per serve — use this where the bake lane's pinning
1243
1242
  (capture-time data for the shell's lifetime) is not acceptable, at the cost
1244
1243
  of a widget-sized fallback in the shell. The slot handler must hand the
@@ -1255,7 +1254,7 @@ their data should bake vs stay live. Your levers, in order of preference:
1255
1254
  and the shell is tag-invalidatable.
1256
1255
 
1257
1256
  The identity rule, stated once: per-user data on a PPR page lives in a
1258
- live-lane loader (no `ssr: false`) consumed CLIENT-side with `useLoader` under
1257
+ live-lane loader (no `ssr: "await"`) consumed CLIENT-side with `useLoader` under
1259
1258
  `loading()` or an inline `<Suspense>`, or in a NESTED promise inside a
1260
1259
  bake-lane loader (a hole, fresh per request). A nested promise's body still
1261
1260
  runs at capture, so it must not call `cookies()`/`headers()` or read
@@ -1283,7 +1282,7 @@ and (in dev, past 2s) the bake-cost warning naming the source.
1283
1282
 
1284
1283
  Three levers, in preference order:
1285
1284
 
1286
- 1. **Make it live**: move the value into a live-lane loader (no `ssr: false`)
1285
+ 1. **Make it live**: move the value into a live-lane loader (no `ssr: "await"`)
1287
1286
  read with `useLoader` under `loading()` or an inline `<Suspense>` — a hole,
1288
1287
  per request, zero capture cost. Inside a bake-lane loader, return the slow
1289
1288
  part as a nested promise instead. Nesting a promise inside a HANDLER's push
@@ -1292,7 +1291,7 @@ Three levers, in preference order:
1292
1291
  tag-invalidatable), but the capture replays the cached value instead of
1293
1292
  re-executing the expensive body (mixed-chain). Choose this for shared,
1294
1293
  expensive-to-compute shell content.
1295
- 3. **Drop `ssr: false`** (loaders only): moves the loader to the live lane —
1294
+ 3. **Drop `ssr: "await"`** (loaders only): moves the loader to the live lane —
1296
1295
  masked at capture, fresh per serve — at the cost of a fallback in the shell
1297
1296
  (a live loader needs `loading()` or an inline `<Suspense>` above its
1298
1297
  reader).
@@ -1304,10 +1303,10 @@ actually paid. A
1304
1303
  Meta pushed by a LIVE-lane loader is different: those loaders are masked at
1305
1304
  capture, so the push happens at request time and applies client-side
1306
1305
  (`metadata.handlesLate`) — it is never in the cached shell's head, by
1307
- construction. A bake-lane (`ssr: false`) loader executes at capture, so its
1306
+ construction. A bake-lane (`ssr: "await"`) loader executes at capture, so its
1308
1307
  settled pushes are shell material like a handler's.
1309
1308
 
1310
- `loader(Def, { ssr: false })` (the document-render await, `/loader`) is the
1309
+ `loader(Def, { ssr: "await" })` (the document-render await, `/loader`) is the
1311
1310
  bake-lane switch under PPR, not a knob for normal renders only: the capture
1312
1311
  render awaits the flagged loader too, so its settled non-promise data — handle
1313
1312
  pushes included — freezes into the stored shell and recurs as capture cost on
@@ -1326,7 +1325,7 @@ replay runs it fresh.
1326
1325
  | Middleware chain | runs (full) | **NOT re-run** — inherits the request's post-middleware context | runs (full) — commit point is after it |
1327
1326
  | `router.match` | runs | re-runs under a derived context | runs (behind the flushed prelude) |
1328
1327
  | Handlers | run | run on UNCACHED segments (`cache()`d segments replay); everything they produce — promises, async server components, handle pushes, awaited loaders — settles before the freeze (`ppr.captureTimeout`) | **never run** — the handler layer is replayed from the shell's recorded segments |
1329
- | Loaders | run **fresh** | LIVE lane (no `ssr: false`): MASKED; BAKE lane (`ssr: false`): execute + snapshot-pin | live: run **fresh**; bake: pinned, runs only if its record has holes |
1328
+ | Loaders | run **fresh** | LIVE lane (no `ssr: "await"`): MASKED; BAKE lane (`ssr: "await"`): execute + snapshot-pin | live: run **fresh**; bake: pinned, runs only if its record has holes |
1330
1329
  | Flight render | full | full, from the capture's own recorded segments (the same bytes every HIT replays) | full (hydration needs the whole payload — no Flight resume) |
1331
1330
  | HTML production | full fizz | `prerender` + abort → prelude + postponed | `resume` only the holes — O(paths to holes) |
1332
1331
  | Shell store | schedules a bg capture | `putShell(key, …)` | `getShell(key)`; a stale/SWR hit also schedules a recapture |
@@ -1345,8 +1344,8 @@ load-bearing: `cookies()`, `headers()`, `ctx.request.headers`,
1345
1344
  `{ cache: false }` variable read THROW during a capture render, and the capture
1346
1345
  is refused even when the code catches that throw, so identity can never leak
1347
1346
  into a shared shell through them. Live-lane loaders (every loader without
1348
- `ssr: false`) are exempt when only a client component reads them: masked at
1349
- capture, they never run there. One a handler or an `ssr: false` loader awaits
1347
+ `ssr: "await"`) are exempt when only a client component reads them: masked at
1348
+ capture, they never run there. One a handler or an `ssr: "await"` loader awaits
1350
1349
  runs at capture, and its identity reads refuse it.
1351
1350
 
1352
1351
  ## allReady: the SEO/bot story
@@ -1376,8 +1375,8 @@ a handler, a promise it passes or pushes, an async server component, a
1376
1375
  bake-lane loader, and a loader a handler awaits (`await ctx.use(Loader)`). The
1377
1376
  capture is refused even if your code catches the throw, and the route keeps
1378
1377
  serving MISSes with a once-per-key warning. `ctx.dynamic()` called there
1379
- refuses it too. The live lane (no `ssr: false`) stays exempt when only a client
1380
- component reads it; one a handler or an `ssr: false` loader awaits runs at
1378
+ refuses it too. The live lane (no `ssr: "await"`) stays exempt when only a client
1379
+ component reads it; one a handler or an `ssr: "await"` loader awaits runs at
1381
1380
  capture, and its identity reads refuse it.
1382
1381
 
1383
1382
  **(c) Residual hazard — middleware-derived per-user state.** A NORMAL `ctx`
@@ -1390,7 +1389,7 @@ middleware-provided session object (`ctx.get("session")`) never calls
1390
1389
  `cookies()` itself, so whatever it returns as settled container data is
1391
1390
  photographed as the CAPTURING user's state. If the value is per-user:
1392
1391
  shell-cache only public/shared pages, keep per-user content in live-lane
1393
- loaders (no `ssr: false`) or nested promises in bake-lane loader data — NOT in
1392
+ loaders (no `ssr: "await"`) or nested promises in bake-lane loader data — NOT in
1394
1393
  handler output or plain bake-lane container data — mark the variable
1395
1394
  `{ cache: false }` so a stray shell read refuses the capture, or key per
1396
1395
  variant at the CDN tier. A variable a middleware sets before `throw rewrite()`
@@ -1456,13 +1455,13 @@ path(
1456
1455
  );
1457
1456
  ```
1458
1457
 
1459
- | Field | Default | Notes |
1460
- | ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1461
- | `ttl` | `300` | shell freshness window in seconds (`ppr: true` uses the default) |
1462
- | `swr` | — | stale window: serve the stale shell + background recapture |
1463
- | `tags` | — | operational tags UNIONED with the tags the capture collects — see "Invalidation" below |
1464
- | `maxSnapshotBytes` | 8 MiB | cap on the loader pins in the entry's snapshot (the bake-lane loader records). The recorded handler layer is exempt. A document HIT is served only from an entry that holds a pin for every `ssr: false` loader its HTML baked, so over the cap no document shell is stored: the entry keeps the handler layer only, documents are a MISS (full SSR, no hydration error, no remount), client navigations still replay the handler layer and run the bake-lane loaders fresh, and the URL backs off like a refused capture. Warned once per key: "the document shell was not stored; raise maxSnapshotBytes or shrink the ssr: false data" |
1465
- | `captureTimeout` | 15000ms | ONE capture deadline: the handler layer settling (promises it passes or pushes, async server components, loaders it awaits), bake-lane loaders, and the prerender; a capture that misses it stores nothing rather than a partial shell |
1458
+ | Field | Default | Notes |
1459
+ | ------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1460
+ | `ttl` | `300` | shell freshness window in seconds (`ppr: true` uses the default) |
1461
+ | `swr` | — | stale window: serve the stale shell + background recapture |
1462
+ | `tags` | — | operational tags UNIONED with the tags the capture collects — see "Invalidation" below |
1463
+ | `maxSnapshotBytes` | 8 MiB | cap on the loader pins in the entry's snapshot (the bake-lane loader records). The recorded handler layer is exempt. A document HIT is served only from an entry that holds a pin for every `ssr: "await"` loader its HTML baked, so over the cap no document shell is stored: the entry keeps the handler layer only, documents are a MISS (full SSR, no hydration error, no remount), client navigations still replay the handler layer and run the bake-lane loaders fresh, and the URL backs off like a refused capture. Warned once per key: "the document shell was not stored; raise maxSnapshotBytes or shrink the ssr: "await" data" |
1464
+ | `captureTimeout` | 15000ms | ONE capture deadline: the handler layer settling (promises it passes or pushes, async server components, loaders it awaits), bake-lane loaders, and the prerender; a capture that misses it stores nothing rather than a partial shell |
1466
1465
 
1467
1466
  A shell never outlives the route `cache()` entry it was captured from: under
1468
1467
  a route `cache()`, the shell is fresh no longer than that entry is (at most
@@ -1511,8 +1510,8 @@ whether from a `"use cache"` function, a `cache()` segment, or a
1511
1510
  render-callable `cacheTag()` in a plain server component (no
1512
1511
  `"use cache"`/`cache()` in its tree) — plus the tags of loaders on the BAKE
1513
1512
  lane (they execute during capture and their data is in the shell). A tag
1514
- recorded outside what the shell renders is not on it. A live-lane loader's tags (every loader without `ssr: false`)
1515
- attach only when a handler or an `ssr: false` loader consumes its value with
1513
+ recorded outside what the shell renders is not on it. A live-lane loader's tags (every loader without `ssr: "await"`)
1514
+ attach only when a handler or an `ssr: "await"` loader consumes its value with
1516
1515
  `ctx.use()`, which bakes it; one read only by the client stays off, since it is masked at capture and
1517
1516
  its hole is already live. `ppr.tags` adds
1518
1517
  operational tags the render cannot know (a tenant id, a deploy marker).
@@ -1537,18 +1536,18 @@ the holes and streams a fresh payload, but does NOT evict the server shell.
1537
1536
  Shell-baked data stays stale until the shell's TTL unless you tag-invalidate it
1538
1537
  (`updateTag` on a shell tag). Data baked into the shell WITHOUT a tag cannot be
1539
1538
  evicted by tag at all — move always-fresh data into a live-lane loader (no
1540
- `ssr: false`) or a nested promise in bake-lane loader data.
1539
+ `ssr: "await"`) or a nested promise in bake-lane loader data.
1541
1540
 
1542
1541
  ## Pitfalls
1543
1542
 
1544
1543
  - **A bake-lane loader that reads `cookies()`/`headers()`/`ctx.request.headers`**: the capture is
1545
1544
  REFUSED (deterministic, once-per-key warned) — the route keeps serving
1546
- MISSes. Move identity onto the live lane (drop `ssr: false`, or split the read into
1545
+ MISSes. Move identity onto the live lane (drop `ssr: "await"`, or split the read into
1547
1546
  a separate unflagged loader; give the reader a boundary). A nested promise
1548
1547
  does not help here: its body still runs during capture.
1549
1548
  - **A bake-lane container that must be fresh per document GET**: it is
1550
1549
  snapshot-pinned for the shell's lifetime by design. Use the live lane
1551
- (no `ssr: false`) or a nested promise instead.
1550
+ (no `ssr: "await"`) or a nested promise instead.
1552
1551
  - **Handler output or a bake-lane loader slower than `ppr.captureTimeout`
1553
1552
  (15s by default)**: the capture stores nothing rather than a partial shell
1554
1553
  (the warning says the output "did not settle within ppr.captureTimeout").
@@ -1569,7 +1568,7 @@ evicted by tag at all — move always-fresh data into a live-lane loader (no
1569
1568
  - **Per-user value in shell material**: baked into the shared shell —
1570
1569
  deterministically, not by race (handler output, promises included, is
1571
1570
  awaited at capture; awaited/resolved values bake everywhere). Put per-user
1572
- data in a live-lane loader (no `ssr: false`) or a nested promise in
1571
+ data in a live-lane loader (no `ssr: "await"`) or a nested promise in
1573
1572
  bake-lane loader data — plain BAKE-lane loader data bakes just like handler
1574
1573
  material.
1575
1574
  - **The session-object bake trap (the guard cannot save you here)**: the
@@ -1594,7 +1593,7 @@ evicted by tag at all — move always-fresh data into a live-lane loader (no
1594
1593
  `return { user: session.user }` bakes it into the shared shell like any
1595
1594
  other settled value — deterministically, not by race. Wrap it in a promise
1596
1595
  (even an already-resolved one) or put the loader on the live lane (drop
1597
- `ssr: false`).
1596
+ `ssr: "await"`).
1598
1597
 
1599
1598
  - **Theme on a HIT is default-then-corrected**: the shell's `initialTheme` is
1600
1599
  the no-cookie default (`defaultTheme`), whoever captured it, and the resume
@@ -1612,7 +1611,7 @@ evicted by tag at all — move always-fresh data into a live-lane loader (no
1612
1611
  the capture read it also rides the shell, so `updateTag` on that tag drops the
1613
1612
  shell too (next request MISSes and recaptures). An untagged entry has no such
1614
1613
  link. If a shell region needs to be fresh, put it under a hole — a live-lane
1615
- loader (no `ssr: false`) behind `loading()` or an inline `<Suspense>`, or a
1614
+ loader (no `ssr: "await"`) behind `loading()` or an inline `<Suspense>`, or a
1616
1615
  nested promise in bake-lane loader data (holes are never pinned) — or make
1617
1616
  the SHELL itself invalidatable by tagging
1618
1617
  it: tag the cached read, call `cacheTag(...)` from the shell-material render
@@ -1628,7 +1627,7 @@ evicted by tag at all — move always-fresh data into a live-lane loader (no
1628
1627
  cached under its own profile; once the entry expires or is invalidated and
1629
1628
  refreshes, the hole shows the refreshed value next to the shell's old one. The
1630
1629
  shell stores no `"use cache"` value, only its recorded handler output and the
1631
- `ssr: false` loaders' baked containers. A hole reads the store even when a
1630
+ `ssr: "await"` loaders' baked containers. A hole reads the store even when a
1632
1631
  bake-lane loader read the same entry at capture: the baked container keeps
1633
1632
  the capture's value, and the hole shows the current entry.
1634
1633
  - **Uncached nondeterminism in server output is frozen, not drifting**: a raw
@@ -1652,7 +1651,7 @@ evicted by tag at all — move always-fresh data into a live-lane loader (no
1652
1651
  - **HIT status is committed at the flush**: a failing hole cannot become a
1653
1652
  500/redirect after the first shell byte — error UI renders inline via
1654
1653
  Suspense/error boundaries (the same property any streamed SSR page has after
1655
- its shell flushes). A MISS has sent nothing yet: an `ssr: false` loader that
1654
+ its shell flushes). A MISS has sent nothing yet: an `ssr: "await"` loader that
1656
1655
  throws answers 500 there with its route's `errorBoundary()` (or the default
1657
1656
  one), and the capture stores nothing.
1658
1657
  - **A shell component that throws during capture refuses it**: an async