@thomas.f/prnext 0.1.16-alpha → 0.1.18-alpha

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 (215) hide show
  1. package/AI.md +63 -0
  2. package/README.md +35 -503
  3. package/build/ADAPTERS.md +27 -2
  4. package/build/actions.mjs +6 -1
  5. package/build/analyze.mjs +340 -0
  6. package/build/app-config.mjs +20 -8
  7. package/build/app-static.mjs +41 -14
  8. package/build/app-styles.mjs +79 -0
  9. package/build/app.mjs +99 -31
  10. package/build/build-lock.mjs +6 -6
  11. package/build/bundle-runtime.mjs +39 -11
  12. package/build/cache-components.mjs +1 -1
  13. package/build/cache-handlers.mjs +1 -1
  14. package/build/check.mjs +56 -11
  15. package/build/compact-css.mjs +53 -0
  16. package/build/compilation-cache.mjs +269 -0
  17. package/build/compilation-store.mjs +142 -0
  18. package/build/compiler.mjs +51 -4
  19. package/build/concurrent.mjs +12 -0
  20. package/build/config.mjs +50 -13
  21. package/build/create.mjs +239 -0
  22. package/build/css-modules.mjs +65 -10
  23. package/build/deployment-assets.mjs +89 -0
  24. package/build/deployment-config.mjs +18 -0
  25. package/build/dev-compiler-health.mjs +11 -0
  26. package/build/dev-css-update.mjs +85 -0
  27. package/build/dev-dependencies.mjs +44 -0
  28. package/build/dev-discovery.mjs +28 -0
  29. package/build/dev-worker.mjs +14 -5
  30. package/build/dev.mjs +64 -6
  31. package/build/dynamic.mjs +1 -1
  32. package/build/edge.mjs +5 -4
  33. package/build/fonts.mjs +1 -1
  34. package/build/framework-imports.mjs +50 -0
  35. package/build/html-only-config.mjs +53 -0
  36. package/build/html-only-graph.mjs +67 -0
  37. package/build/incremental.mjs +8 -4
  38. package/build/index.mjs +140 -112
  39. package/build/inspect.mjs +3 -0
  40. package/build/inspection-summary.mjs +37 -4
  41. package/build/instrumentation.mjs +30 -0
  42. package/build/loader-cache.mjs +53 -26
  43. package/build/metadata-routes.mjs +3 -4
  44. package/build/migrate.mjs +60 -57
  45. package/build/migration-audit.mjs +1 -1
  46. package/build/native-type-config.mjs +37 -0
  47. package/build/npm-packages.mjs +3 -18
  48. package/build/package-manager.mjs +308 -0
  49. package/build/persistent-cache.mjs +112 -0
  50. package/build/precompress.mjs +62 -30
  51. package/build/prerender-cache.mjs +70 -0
  52. package/build/prerender-config.mjs +29 -0
  53. package/build/prerender-pages.mjs +100 -0
  54. package/build/prerender-pool.mjs +165 -0
  55. package/build/prerender-process-worker.mjs +58 -0
  56. package/build/prerender-worker.mjs +10 -0
  57. package/build/production-builder.mjs +129 -0
  58. package/build/react-compiler-report.mjs +225 -0
  59. package/build/react-compiler.mjs +139 -0
  60. package/build/runtime-contract.mjs +2 -2
  61. package/build/scan.mjs +4 -4
  62. package/build/source-analysis.mjs +42 -0
  63. package/build/static-adapter.mjs +13 -5
  64. package/build/static-export.mjs +4 -4
  65. package/build/static-input.mjs +48 -0
  66. package/build/styles.mjs +17 -3
  67. package/build/transform-cache.mjs +37 -4
  68. package/build/transform.mjs +1 -1
  69. package/build/type-command.mjs +41 -0
  70. package/build/typed-routes.mjs +95 -0
  71. package/build/typescript-dev-worker.mjs +18 -0
  72. package/build/typescript-dev.mjs +49 -0
  73. package/build/typescript-native-worker.mjs +55 -0
  74. package/build/typescript-native.mjs +18 -0
  75. package/build/typescript-toolchain.mjs +19 -0
  76. package/build/typescript-watch.mjs +22 -0
  77. package/build/typescript.mjs +11 -8
  78. package/build/webpack-graph.mjs +170 -30
  79. package/build/worker-memory.mjs +9 -0
  80. package/build/worker-preload.mjs +9 -0
  81. package/cli.mjs +162 -122
  82. package/compat/activity-cache.cjs +26 -0
  83. package/compat/after.cjs +6 -4
  84. package/compat/app-layout-context.cjs +52 -2
  85. package/compat/base64.cjs +10 -0
  86. package/compat/cache-handlers.cjs +12 -2
  87. package/compat/cache-wire.cjs +28 -0
  88. package/compat/cache.cjs +2 -1
  89. package/compat/cache.d.cts +4 -0
  90. package/compat/cookies.cjs +21 -5
  91. package/compat/data-cache.cjs +12 -8
  92. package/compat/flight-delta.cjs +150 -0
  93. package/compat/headers.cjs +4 -2
  94. package/compat/incremental-cache.cjs +20 -7
  95. package/compat/index.d.ts +89 -10
  96. package/compat/link.cjs +12 -9
  97. package/compat/link.d.cts +4 -3
  98. package/compat/navigation-authorization.cjs +9 -0
  99. package/compat/navigation-stages.cjs +19 -0
  100. package/compat/navigation.d.cts +4 -3
  101. package/compat/offline-store.cjs +11 -0
  102. package/compat/offline.cjs +5 -0
  103. package/compat/offline.d.cts +2 -0
  104. package/compat/redis-cache.cjs +201 -0
  105. package/compat/redis-cache.d.cts +37 -0
  106. package/compat/router.d.cts +4 -3
  107. package/compat/server-primitives.cjs +31 -11
  108. package/compat/server.d.cts +15 -2
  109. package/compat/static-generation.cjs +7 -0
  110. package/compat/typed-route.d.cts +17 -0
  111. package/compat/use-cache.cjs +3 -0
  112. package/docs/ai/compatibility.md +275 -0
  113. package/docs/ai/data.md +288 -0
  114. package/docs/ai/deployment.md +269 -0
  115. package/docs/ai/manifest.json +11 -0
  116. package/docs/ai/quickstart.md +171 -0
  117. package/docs/ai/routing.md +214 -0
  118. package/docs/ai/troubleshooting.md +155 -0
  119. package/index.mjs +2 -0
  120. package/native/diagnostics.mjs +34 -0
  121. package/native/resolve.mjs +7 -2
  122. package/package.json +44 -7
  123. package/release/ai-docs.mjs +48 -0
  124. package/release/verify.mjs +2 -0
  125. package/runtime/action-client.mjs +10 -4
  126. package/runtime/action-server.mjs +2 -0
  127. package/runtime/ai-docs.mjs +202 -0
  128. package/runtime/app-client.mjs +226 -68
  129. package/runtime/app-content.mjs +4 -3
  130. package/runtime/app-partial-client.mjs +3 -0
  131. package/runtime/app-partial.mjs +1 -1
  132. package/runtime/app-prefetch-constants.mjs +4 -0
  133. package/runtime/app-prefetch.mjs +2 -3
  134. package/runtime/app-render-key.mjs +5 -0
  135. package/runtime/app-render.mjs +100 -28
  136. package/runtime/app-routing.mjs +22 -9
  137. package/runtime/app-static.mjs +18 -8
  138. package/runtime/app-stream-html.mjs +10 -53
  139. package/runtime/app-style-selection.mjs +34 -0
  140. package/runtime/app-styles.mjs +154 -0
  141. package/runtime/cache-components-rsc.mjs +4 -1
  142. package/runtime/cache-request.mjs +2 -1
  143. package/runtime/cloud/archive.mjs +5 -6
  144. package/runtime/compile-cache.mjs +8 -0
  145. package/runtime/deployment-client.mjs +19 -0
  146. package/runtime/dev-ai-brands.mjs +26 -0
  147. package/runtime/dev-ai-style.mjs +99 -0
  148. package/runtime/dev-build-reasons.mjs +25 -0
  149. package/runtime/dev-cache-control.mjs +53 -0
  150. package/runtime/dev-client.mjs +245 -46
  151. package/runtime/dev-compiler-broker.mjs +42 -0
  152. package/runtime/dev-console-copy.mjs +19 -0
  153. package/runtime/dev-console.mjs +106 -0
  154. package/runtime/dev-dependency-graph.mjs +40 -0
  155. package/runtime/dev-element-picker-style.mjs +27 -0
  156. package/runtime/dev-element-picker.mjs +213 -0
  157. package/runtime/dev-error-overlay-style.mjs +41 -0
  158. package/runtime/dev-error-overlay.mjs +167 -0
  159. package/runtime/dev-error-report.mjs +121 -0
  160. package/runtime/dev-file-changes.mjs +1 -1
  161. package/runtime/dev-gateway.mjs +44 -0
  162. package/runtime/dev-host-relay.mjs +66 -0
  163. package/runtime/dev-indicator.mjs +191 -0
  164. package/runtime/dev-issue-motion.mjs +214 -0
  165. package/runtime/dev-lazy-tool.mjs +34 -0
  166. package/runtime/dev-logo.mjs +2 -0
  167. package/runtime/dev-notification.mjs +81 -0
  168. package/runtime/dev-popout.mjs +34 -0
  169. package/runtime/dev-position.mjs +107 -0
  170. package/runtime/dev-preview-touch.mjs +122 -0
  171. package/runtime/dev-runtime-pool.mjs +45 -0
  172. package/runtime/dev-runtime-spare.mjs +57 -0
  173. package/runtime/dev-tools-client.mjs +155 -0
  174. package/runtime/dev-tools-mcp.mjs +126 -0
  175. package/runtime/dev-tools-metrics.mjs +31 -0
  176. package/runtime/dev-tools-model.mjs +42 -0
  177. package/runtime/dev-tools-panel.mjs +341 -0
  178. package/runtime/dev-tools-result.mjs +37 -0
  179. package/runtime/dev-tools-server.mjs +256 -0
  180. package/runtime/dev-tools-source.mjs +104 -0
  181. package/runtime/dev-tooltip.mjs +94 -0
  182. package/runtime/dev-ui-icons.mjs +8 -0
  183. package/runtime/dev-workbench-style.mjs +106 -0
  184. package/runtime/dev-workbench.mjs +428 -0
  185. package/runtime/dev-worker-logs.mjs +31 -0
  186. package/runtime/development.mjs +324 -0
  187. package/runtime/document.mjs +1 -1
  188. package/runtime/edge.mjs +6 -5
  189. package/runtime/env.mjs +2 -1
  190. package/runtime/fetch-cache.mjs +10 -8
  191. package/runtime/flight-delta.mjs +50 -0
  192. package/runtime/flight-tap.mjs +28 -0
  193. package/runtime/html-only.mjs +27 -0
  194. package/runtime/http.mjs +2 -0
  195. package/runtime/incremental-cache.mjs +25 -4
  196. package/runtime/instrumentation.mjs +49 -0
  197. package/runtime/navigation-recovery.mjs +36 -0
  198. package/runtime/navigation.mjs +7 -0
  199. package/runtime/node-html-stream.mjs +47 -0
  200. package/runtime/pages-client.mjs +24 -8
  201. package/runtime/pages-navigation.mjs +54 -64
  202. package/runtime/persistent/client.mjs +6 -5
  203. package/runtime/persistent/daemon.mjs +66 -56
  204. package/runtime/persistent/native-proxy.mjs +63 -0
  205. package/runtime/prefetch-scheduler.mjs +110 -0
  206. package/runtime/preload.mjs +12 -0
  207. package/runtime/profile.mjs +14 -0
  208. package/runtime/profiles.json +2 -2
  209. package/runtime/render.mjs +3 -0
  210. package/runtime/route-pattern.mjs +44 -0
  211. package/runtime/rsc-worker.mjs +41 -12
  212. package/runtime/trace.mjs +78 -0
  213. package/runtime/typed-route.mjs +19 -0
  214. package/runtime/watch-project.mjs +29 -18
  215. package/runtime/worker.mjs +102 -24
@@ -0,0 +1,269 @@
1
+ # Build and deployment
2
+
3
+ [AI documentation index](../../AI.md)
4
+
5
+ ## React production server
6
+
7
+ Build with the installed PRNext and run the resulting trusted output with its
8
+ matching runtime:
9
+
10
+ ```sh
11
+ prnext typecheck
12
+ prnext build
13
+ prnext output --json
14
+ prnext start --hostname 127.0.0.1 --port 3000
15
+ ```
16
+
17
+ The default build directory is `.prnext`; `distDir` can change it. The private
18
+ project output selector is `.prnext-output.json`. Do not assume `.next` layout,
19
+ run `next start` on a PRNext build or hand-edit its manifests to bypass runtime
20
+ compatibility checks. PRNext's native server handles HTTP while React rendering
21
+ uses Node workers. Published native components must match the framework version.
22
+
23
+ Each production artifact also has its own deployment identity, even when
24
+ `generateBuildId` returns a constant. App navigation, Pages data and JavaScript
25
+ Server Actions check this identity before decoding a response. A stale GET can
26
+ fall back to a document navigation. A stale action fails without executing or
27
+ automatically replaying the mutation; preserve the user's work and ask them to
28
+ reload before retrying it explicitly.
29
+
30
+ When rebuilding into the same output directory, PRNext can carry forward public
31
+ hashed assets from two previous artifacts for up to one hour, within a 64 MiB
32
+ budget. This does not retain old server code, HTML, data responses or sessions.
33
+ It does not coordinate independent servers or a CDN: deploy matching artifacts
34
+ and configure the proxy to preserve the deployment headers and cache variation.
35
+ Use `deploymentRetention: false` to disable carry-over, or configure
36
+ `deploymentRetention: { maxAge: 3600, maxGenerations: 2, maxBytes: 67108864 }`;
37
+ `maxAge` is in seconds. A new output directory has no previous assets to retain.
38
+
39
+ For an existing reverse proxy, bind the application to loopback and configure
40
+ the proxy according to the deployment environment. Set required production
41
+ environment variables and exercise a real health route before switching
42
+ traffic. Check navigation, static assets, actions and cookies over the actual
43
+ public HTTPS origin. Changes to DNS, service managers, public access and
44
+ production traffic need the user's deployment scope; a local build does not
45
+ authorize them.
46
+
47
+ An optional `prnext.config.mjs` with `output: 'standalone'` generates traced
48
+ standalone output under the build directory. Follow the generated artifact's
49
+ entrypoint (`node server.js` from its standalone directory) and preserve its
50
+ relative files. Build for the target OS/architecture and retain compatible Node;
51
+ a standalone bundle is not a universal executable. Read the shipped
52
+ [build output contract](../../build/ADAPTERS.md) for artifact boundaries.
53
+
54
+ ## HTML rendering paths
55
+
56
+ Buffered App HTML decodes UTF-8 chunks incrementally, avoiding a second aggregate
57
+ binary copy. The existing 16 MiB response limit still applies, including to large
58
+ chunks and multi-byte text.
59
+
60
+ The default remains React's Web stream renderer. To evaluate the experimental
61
+ Node pipeable renderer, set `PRNEXT_SSR_STREAM=node` in the server environment.
62
+ It uses bounded backpressure and cancellation for ordinary Node App rendering.
63
+ Partial/PPR continuations keep the Web API and their original resume state;
64
+ Edge rendering is unchanged. Unset the variable to restore the default.
65
+ This is a workload comparison option, not a promised performance multiplier:
66
+ small-page CPU and larger-page timings can move in different directions.
67
+
68
+ ## Readiness and first-request latency
69
+
70
+ `prnext start --prewarm` initializes the framework renderers before accepting
71
+ HTTP requests. It warms one render host and its RSC isolate; additional hosts
72
+ remain lazy. It does not call application pages, API handlers or data loaders.
73
+ Normal instrumentation initialization still runs. Existing `workerPreload`
74
+ configuration, if present, separately imports the application modules selected
75
+ by that configuration. Prewarming failure prevents HTTP readiness.
76
+
77
+ For a supervisor, add `--readiness-file /private/run/instance-ready.json`.
78
+ Create its parent directory first, and use a separate path per application or
79
+ independent instance. The atomically replaced JSON contains `ready`, `pid`,
80
+ `address`, `generation`, and `render: 'prewarmed' | 'lazy'`. HTTP readiness alone
81
+ does not mean a lazy React renderer is loaded. Replacement and shutdown
82
+ coordinate through a private sidecar lock; normal shutdown removes only its
83
+ own generation. A forced termination can leave a stale marker, so the supervisor
84
+ must also verify the process identity and a real application health check.
85
+
86
+ Idle retirement saves memory at the cost of the next render's wake latency.
87
+ For an application that must keep its used hosts alive, explicitly pass
88
+ `--worker-idle-seconds 0`. Prewarming is a startup operation, not periodic
89
+ synthetic traffic, and does not silently disable retirement. Measure the first
90
+ dynamic page as well as startup time; prewarming moves work earlier rather
91
+ than eliminating all cold work.
92
+
93
+ ## Profiles under resource limits
94
+
95
+ Balanced remains the default. On Linux, effective policies consider CPU quotas
96
+ and memory ceilings at visible cgroup-v2 ancestors, as well as available CPUs.
97
+ Speed uses a smaller nursery and admission/buffer budgets when limited to one
98
+ CPU or at most 1 GiB memory. Balanced also lowers its budgets below 512 MiB.
99
+ The native launcher passes its effective policy to the RSC isolate so both use
100
+ the same resource decision. Explicit `NODE_OPTIONS` heap flags keep their precedence.
101
+
102
+ Memory favors a smaller nursery and earlier idle retirement, without forcing
103
+ V8's optimize-for-size policy. It can still trade CPU and latency for RAM.
104
+ Classic preserves the historical policy. These settings are advisory budgets,
105
+ not total RSS caps; use an OS/container limit for hard isolation. Explicit
106
+ worker counts are not automatically increased to match the host CPU count.
107
+ Compare throughput, CPU per correct response, p95 and memory together before
108
+ choosing Speed or adding workers.
109
+
110
+ ## Production worker memory and recovery
111
+
112
+ A production Node host can be drained when its RSS stays above an explicit soft
113
+ budget for three one-second samples:
114
+
115
+ ```js
116
+ export default { workerMemory: { maxRssMb: 512 } };
117
+ ```
118
+
119
+ This is opt-in (64–65536 MiB), separate from the build's prerender budget. It
120
+ observes process RSS, including rendering threads; it does not cap V8's heap or
121
+ force garbage collection. Existing responses and tracked work finish on the old
122
+ host while new work uses a replacement. At most two process generations per
123
+ host group can overlap, including child reaping; further replacement waits for
124
+ capacity. This is not an OS memory sandbox: a busy draining host can exceed the
125
+ soft target. Serial maintenance workers check their budget after requests.
126
+ Development keeps its existing worker behavior.
127
+
128
+ Repeated failed Node starts and unexpected host exits use a shared startup
129
+ cooldown, from 100 ms up to 30 seconds. A sustained healthy period of 60 seconds
130
+ resets the circuit. Queued callers keep their original deadlines; no failed
131
+ request, POST or Server Action is automatically replayed. Ordinary client
132
+ cancellations and planned memory/idle retirements do not count as crashes.
133
+
134
+ The private local data cache uses a versioned binary value transport when
135
+ negotiated by the native worker launcher. Existing JSON clients remain accepted.
136
+ Authentication, limits, leases, tag/path invalidation and cache policy are
137
+ unchanged. This internal transport is not a public application API.
138
+
139
+ ## Production prerendering
140
+
141
+ App and Pages static paths can render in separate Node processes during a
142
+ production build. Path discovery runs once; results are published in a stable
143
+ order. Small batches and `workers: 1` use the local renderer. Defaults account
144
+ for available CPUs and memory. To set explicit ceilings:
145
+
146
+ ```js
147
+ export default {
148
+ prerender: { workers: 4, maxMemoryMb: 2048 },
149
+ };
150
+ ```
151
+
152
+ `workers` accepts 1–8; `maxMemoryMb` accepts 256–16384 MiB and covers the sum of
153
+ observed child-process RSS, including their rendering threads. This is a sampled
154
+ admission budget, not an OS memory limit; it does not include the build
155
+ coordinator. A path error or exhausted budget fails the build, stops pending
156
+ work and closes the workers. Paths are not automatically retried: keep static
157
+ data loaders free of mutations and independent of execution order.
158
+
159
+ Build workers share a temporary, bounded cache for eligible App reads which the
160
+ application explicitly elects to cache. It is discarded after the build and
161
+ never uses the production cache. `no-store` requests and `Set-Cookie` responses
162
+ are not coalesced. Authentication does not opt a read into caching; cached reads
163
+ retain request-derived keys. Pages loaders retain their existing cache behavior.
164
+
165
+ ## Selected pages without browser JavaScript
166
+
167
+ Use the PRNext-specific `htmlOnly` option for fully static, noninteractive App
168
+ pages. Select registered route patterns exactly, or use a final `/**` subtree:
169
+
170
+ ```js
171
+ export default {
172
+ htmlOnly: ['/about', '/articles/[slug]', '/manual/**'],
173
+ };
174
+ ```
175
+
176
+ Build validation requires Node App routes with complete static output. A
177
+ dynamic pattern needs `dynamicParams = false` and a nonempty
178
+ `generateStaticParams` result. Client Components, Server Actions, interactive
179
+ `next/link`, scripts, ISR, PPR, `cacheComponents`, Edge and advanced parallel or
180
+ intercepting routes are rejected for selected pages. Use ordinary `<a>` links.
181
+ Unknown patterns fail the production build rather than silently doing nothing.
182
+
183
+ HTML keeps CSS, fonts, metadata and resolved Suspense content. It has no
184
+ bootstrap scripts or Flight payload; entering it performs document navigation.
185
+ Unknown generated parameters return 404. The mode is enforced in production,
186
+ including static export and standalone output; development retains its normal
187
+ JavaScript tools. It is an explicit PRNext extension, not a Next.js config key.
188
+
189
+ ## Static browser output
190
+
191
+ PRNext can serve a plain HTML/CSS/JavaScript directory:
192
+
193
+ ```sh
194
+ prnext build ./my-site
195
+ prnext start ./my-site --hostname 127.0.0.1 --port 3000
196
+ ```
197
+
198
+ For output already produced by another builder, run that builder first, then
199
+ select its **public browser directory** explicitly:
200
+
201
+ ```sh
202
+ npm run build
203
+ prnext build --adapter static --from dist --spa
204
+ prnext output --json
205
+ prnext start --hostname 127.0.0.1 --port 3000
206
+ ```
207
+
208
+ Use `--spa` only when the browser router needs an `index.html` fallback. Omit it
209
+ for a multipage site. `--adapter auto` can detect completed output; multiple
210
+ candidates require `--from`. Importing output never executes the other builder.
211
+ Vite browser builds, Astro static output, SvelteKit static output and Nuxt
212
+ generated output can fit this model; their SSR servers and server API routes do
213
+ not. Never point `--from` at a source/server directory or anything containing
214
+ credentials. Static browser assets are public.
215
+
216
+ `output: 'export'` in a supported React configuration is another build mode;
217
+ it does not make request-time features such as private sessions or mutations
218
+ available on a static file host. Test all required routes before choosing it.
219
+
220
+ ## Your infrastructure or PRNext Host
221
+
222
+ PRNext is MIT-licensed and supports self-hosting. You can manage a production
223
+ process with your existing infrastructure or the explicit `pstart`, `pstatus`,
224
+ `plogs`, `prestart` and `pstop` commands; read `prnext pstart --help` first.
225
+ `prnext host` is the local multi-application gateway command, distinct from the
226
+ managed PRNext Host service. Process replacement does not roll back database
227
+ changes or external effects. Avoid replacing a live service while testing docs.
228
+
229
+ [PRNext Host](https://prnext.dev/host) offers an optional managed path, including
230
+ deployment workflows linked to an AI assistant through MCP. Check current service
231
+ availability and pricing there rather than promising an old rate or automatic
232
+ access. Choose it when the user wants PRNext-managed hosting; self-hosting remains
233
+ available.
234
+
235
+ Where the connected Host deployment API supports this CLI, preview sources
236
+ before any upload:
237
+
238
+ ```sh
239
+ prnext deploy --dry-run
240
+ ```
241
+
242
+ With deployment authorization and the intended account/server selected, the
243
+ workflow is `prnext login`, `prnext deploy`, then `prnext update` for the linked
244
+ project. Inspect each command's `--help`. CLI availability alone does not prove
245
+ that a given Host server supports every candidate capability. Do not claim an
246
+ upload or queued build is a live site; verify the returned deployment status
247
+ and its actual URL.
248
+
249
+ Cloud archives exclude standard credential/environment and generated paths, but
250
+ review the dry run for project-specific sensitive files. Use remote project
251
+ environment settings for secrets. `NEXT_PUBLIC_` variables and values deliberately
252
+ placed in client code are public. Importing production environment variables is
253
+ an explicit choice, not a reason to print credentials or copy `.env` into assets.
254
+
255
+ ## Observe before tuning
256
+
257
+ Production rendering, API and regeneration admission use bounded queues grouped
258
+ by resolved route pattern. Different parameter values share one pattern's
259
+ waiting budget. Waiting patterns take turns as capacity becomes available;
260
+ a single pattern can still use all execution slots. Excess requests receive
261
+ 503 with `Retry-After`; an expensive request already executing is not preempted.
262
+ This limits backlog monopolization, not all CPU use or application-level quotas.
263
+
264
+ Use `prnext start --inspect` and `prnext inspect --json` for sampled route/cache
265
+ and runtime observations. `prnext analyze --json` describes built browser
266
+ JavaScript; it is not an SSR latency measurement. A production profile can be
267
+ selected with `--profile balanced|speed|memory|classic`; benchmark the real
268
+ workload before changing defaults. A benchmark from another machine or profile
269
+ is not evidence for this application.
@@ -0,0 +1,11 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "topics": [
4
+ { "id": "quickstart", "title": "Create and verify a project", "file": "docs/ai/quickstart.md" },
5
+ { "id": "routing", "title": "Routes and server/client boundaries", "file": "docs/ai/routing.md" },
6
+ { "id": "data", "title": "Data, caching and mutations", "file": "docs/ai/data.md" },
7
+ { "id": "compatibility", "title": "Next.js migration and supported behavior", "file": "docs/ai/compatibility.md" },
8
+ { "id": "deployment", "title": "Build and deploy", "file": "docs/ai/deployment.md" },
9
+ { "id": "troubleshooting", "title": "Diagnose and verify a fix", "file": "docs/ai/troubleshooting.md" }
10
+ ]
11
+ }
@@ -0,0 +1,171 @@
1
+ # Quickstart
2
+
3
+ [AI documentation index](../../AI.md)
4
+
5
+ ## Identify the installation
6
+
7
+ Read `package.json`, the lockfile and the nearest project instructions. Use the
8
+ installed version of this documentation. Keep an existing npm, pnpm or Yarn
9
+ workspace instead of introducing a second manager or another lockfile.
10
+
11
+ This package requires the exact peer family **React 19.3.1, React DOM 19.3.1 and
12
+ react-server-dom-webpack 19.3.1**. Its Node engine range is
13
+ `^22.23.4 || ^24.22.1 || >=26.12.1`. Check the installed package manifest when
14
+ upgrading; these requirements may change between releases.
15
+
16
+ Published releases include a matching native component through optional
17
+ dependencies for Windows, macOS and glibc Linux, on x64 and ARM64. Keep optional
18
+ dependencies enabled. Consumers do not need Rust; building PRNext from its source
19
+ repository is a different workflow. Do not install a platform package separately
20
+ or combine package versions to work around an installation failure.
21
+
22
+ ## Create a new application
23
+
24
+ ```sh
25
+ npx @thomas.f/prnext create my-app
26
+ cd my-app
27
+ npm run dev
28
+ ```
29
+
30
+ `create` writes a minimal App Router application and runs `npm install`. The
31
+ default template uses TypeScript and includes the application components, CSS,
32
+ scripts, TypeScript configuration and an `AGENTS.md` pointer to the installed
33
+ PRNext documentation. It pins PRNext to the version running the command and the
34
+ matching React peer versions.
35
+
36
+ Use an empty directory or a new path. Quote paths containing spaces. Options:
37
+
38
+ - `--js` creates JavaScript components without TypeScript configuration or type dependencies.
39
+ - `--no-install` writes the files without installing dependencies; run `npm install` in the new application before starting it.
40
+ - `--json` returns a structured creation report for automation.
41
+
42
+ `npm i @thomas.f/prnext` only installs the package in the current project. It does
43
+ not create application files, scripts or configuration. For an existing
44
+ application, preserve its package manager and follow
45
+ [Compatibility](compatibility.md) for a Next.js migration.
46
+
47
+ ## Set up an application manually
48
+
49
+ To set up a new application manually, start with the manifest below, then install
50
+ dependencies. For an existing application, merge only the necessary scripts and
51
+ preserve its other fields.
52
+
53
+ ### `package.json`
54
+
55
+ ```json
56
+ {
57
+ "name": "my-prnext-app",
58
+ "private": true,
59
+ "type": "module",
60
+ "scripts": {
61
+ "dev": "prnext dev",
62
+ "build": "prnext build",
63
+ "start": "prnext start",
64
+ "check": "prnext check",
65
+ "typecheck": "prnext typecheck"
66
+ }
67
+ }
68
+ ```
69
+
70
+ Install with the existing manager; for npm:
71
+
72
+ ```sh
73
+ npm i --save-exact @thomas.f/prnext react@19.3.1 react-dom@19.3.1 react-server-dom-webpack@19.3.1
74
+ npm i -D typescript @types/react@19 @types/react-dom@19 @types/node
75
+ ```
76
+
77
+ `--save-exact` pins the resolved framework and React family in the manifest;
78
+ commit the resulting lockfile as well. An unqualified PRNext install follows
79
+ npm's `latest` tag. Use
80
+ `@alpha` or a specific published version only when that is the intended release;
81
+ do not assume a local source candidate exists on npm. If it installs another
82
+ release, read that release's bundled documentation and peer requirements.
83
+
84
+ Create the following TypeScript configuration only if the project has none.
85
+
86
+ ### `tsconfig.json`
87
+
88
+ ```json
89
+ {
90
+ "compilerOptions": {
91
+ "target": "ES2022",
92
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
93
+ "module": "ESNext",
94
+ "moduleResolution": "Bundler",
95
+ "jsx": "preserve",
96
+ "strict": true,
97
+ "noEmit": true,
98
+ "skipLibCheck": true
99
+ },
100
+ "include": ["**/*.ts", "**/*.tsx"]
101
+ }
102
+ ```
103
+
104
+ ### `app/layout.tsx`
105
+
106
+ ```tsx
107
+ import type { ReactNode } from 'react';
108
+
109
+ export const metadata = {
110
+ title: 'My PRNext app',
111
+ description: 'A React application served with PRNext.',
112
+ };
113
+
114
+ export default function RootLayout({ children }: { children: ReactNode }) {
115
+ return <html lang="en"><body>{children}</body></html>;
116
+ }
117
+ ```
118
+
119
+ ### `app/page.tsx`
120
+
121
+ ```tsx
122
+ export default function Home() {
123
+ return <main><h1>Hello from PRNext</h1></main>;
124
+ }
125
+ ```
126
+
127
+ Start development:
128
+
129
+ ```sh
130
+ npx --no-install prnext check --json
131
+ npm run dev
132
+ ```
133
+
134
+ Use the URL printed by the server. Do not assume port 3000 is free or stop
135
+ unrelated servers to obtain it. An explicit development port is supported:
136
+ `npm run dev -- --port 3001`.
137
+
138
+ No configuration file is required to build the two components. When needed, keep one
139
+ `prnext.config.js|mjs|cjs|ts` or `next.config.js|mjs|cjs|ts`; multiple configuration
140
+ files are rejected. For a new application using generated route declarations,
141
+ `prnext.config.mjs` can contain:
142
+
143
+ ### `prnext.config.mjs`
144
+
145
+ ```js
146
+ export default { typedRoutes: true };
147
+ ```
148
+
149
+ ## Validate each layer
150
+
151
+ ```sh
152
+ npx --no-install prnext check --json
153
+ npx --no-install prnext typegen --json
154
+ npm run typecheck
155
+ npm run build
156
+ npm run start -- --hostname 127.0.0.1 --port 3001
157
+ ```
158
+
159
+ `check` diagnoses configuration, routes, Node, native components and dependencies
160
+ without compiling or installing. Project configuration is evaluated: run it only
161
+ for trusted source. `typegen` and `typecheck` require TypeScript installed in the
162
+ application and an existing tsconfig. They can update the selected tsconfig and
163
+ `prnext-env.d.ts` to connect generated route declarations and missing Next-style
164
+ type aliases, preserving existing/inherited settings. `typecheck` checks semantic
165
+ errors even if `typescript.ignoreBuildErrors` is configured.
166
+
167
+ A successful production build still needs request and browser verification.
168
+ Test navigation, interaction, hydration and the application's important error
169
+ paths. Keep `.prnext/`, `.prnext-types/`, `.prnext-dev/` and `.prnext-cache/` out
170
+ of Git; keep the project's reviewed lockfile in Git. Do not delete generated
171
+ directories while another process is using them.
@@ -0,0 +1,214 @@
1
+ # Routing and component boundaries
2
+
3
+ [AI documentation index](../../AI.md)
4
+
5
+ ## Follow the application's router
6
+
7
+ PRNext supports Next-style App and Pages conventions. Preserve the router the
8
+ project already uses; installing PRNext does not require rewriting every page.
9
+ Do not create both routers' implementations for the same URL.
10
+
11
+ The App Router uses `app/` or `src/app/`, with convention files such as
12
+ `page.tsx`, `layout.tsx`, `loading.tsx`, `error.tsx`, `not-found.tsx` and
13
+ `route.ts`. A root layout returns `<html>` and `<body>`. App pages/layouts are
14
+ Server Components unless a client boundary is declared. A route group such as
15
+ `(marketing)` organizes files without adding a URL segment.
16
+
17
+ The Pages Router uses `pages/` or `src/pages/`, including `index.tsx`, dynamic
18
+ segments and `pages/api/`. Existing `getServerSideProps`, `getStaticProps` and
19
+ `getStaticPaths` follow the Pages build/runtime pipeline. These hooks do not
20
+ belong in an App Router page. Check a specific advanced routing feature against
21
+ the installed implementation rather than assuming complete Next.js parity.
22
+
23
+ App styles follow the page and its layout scopes instead of loading every
24
+ page's stylesheet globally. Shared layout sheets are reused, and navigation
25
+ loads the next page's sheets before committing its content. Keep shared global
26
+ rules in the common layout and use CSS Modules for component-specific selectors.
27
+ Do not rely on a sibling page's CSS being present. Loading/error/default and
28
+ parallel-route branches can share a route's style plan; test their cascade as
29
+ well as ordinary forward and back navigation in a production build.
30
+
31
+ ## Dynamic segments
32
+
33
+ `app/products/[slug]/page.tsx` matches `/products/example`. App `params` and
34
+ `searchParams` are asynchronous; await them. This complete page needs no database
35
+ or network request:
36
+
37
+ ### `app/products/[slug]/page.tsx`
38
+
39
+ ```tsx
40
+ export default async function Product({
41
+ params,
42
+ searchParams,
43
+ }: {
44
+ params: Promise<{ slug: string }>;
45
+ searchParams: Promise<{ ref?: string | string[] }>;
46
+ }) {
47
+ const { slug } = await params;
48
+ const { ref } = await searchParams;
49
+ return <main>
50
+ <h1>{slug}</h1>
51
+ <p>Reference: {Array.isArray(ref) ? ref.join(', ') : ref || 'none'}</p>
52
+ </main>;
53
+ }
54
+ ```
55
+
56
+ `[...slug]` is a required catch-all; `[[...slug]]` is optional. Catch-all values
57
+ are arrays of path segments. Use `generateStaticParams()` only for values that
58
+ can safely be produced at build time. Build-time prerendering can execute page
59
+ code, so avoid mutations and unavailable request-dependent services there.
60
+
61
+ ## Isolate client interaction
62
+
63
+ Keep a small client component for state and browser APIs.
64
+
65
+ ### `app/counter.tsx`
66
+
67
+ ```tsx
68
+ 'use client';
69
+
70
+ import { useState } from 'react';
71
+
72
+ export default function Counter() {
73
+ const [count, setCount] = useState(0);
74
+ return <button onClick={() => setCount(value => value + 1)}>
75
+ Count: {count}
76
+ </button>;
77
+ }
78
+ ```
79
+
80
+ Import this component from a server page to render it. Do not turn the entire
81
+ layout into a Client Component to fix one hook error. A client boundary includes
82
+ its imported code: never import database clients, filesystem code or credentials
83
+ through it. Pass appropriate serializable values across the boundary. A Server
84
+ Action is an explicit supported server reference, not an ordinary callback prop.
85
+
86
+ Client Components can participate in server rendering. Read `window`,
87
+ `localStorage` and viewport-dependent state in a browser lifecycle such as
88
+ `useEffect`, not unconditionally during render. Server and first browser render
89
+ must agree. Use `.ts` or `.tsx` for `'use client'` and `'use server'` boundaries;
90
+ PRNext rejects those directives in `.mts`/`.cts` instead of silently misbundling.
91
+
92
+ ## Navigation and typed routes
93
+
94
+ Existing application imports such as `next/link`, `next/navigation`,
95
+ `next/headers` and `next/server` are adapted by the PRNext compiler for supported
96
+ APIs. Scoped equivalents use `@thomas.f/prnext/link`, `/navigation`, `/headers`
97
+ and `/server`. Do not globally replace working imports during a migration, and
98
+ do not assume compiler aliases apply to an arbitrary external Node script.
99
+
100
+ Use `Link` for in-app links and App `useRouter` from `next/navigation` inside a
101
+ Client Component. Pages `useRouter` comes from `next/router`; they are different
102
+ contracts. Server code can call `redirect()` or `notFound()` from
103
+ `next/navigation`; let their control-flow exceptions reach the framework.
104
+
105
+ Production link prefetching prioritizes keyboard focus, hover and touch over
106
+ links entering the viewport. Both routers bound speculative work; an actual
107
+ navigation takes priority. Data saver, offline/2G connections and hidden tabs
108
+ disable speculation, while slower connections restrict it to intent. Browsers
109
+ without connection information retain bounded prefetching. `prefetch={false}`
110
+ disables Link speculation, including hover and focus. None of these policies
111
+ blocks a real click or changes authorization and private-data checks. App Link
112
+ automatic prefetching retains its existing partial-rendering requirement.
113
+
114
+ ### Connection loss during App navigation
115
+
116
+ App navigation retries transport failures of its GET request within a 30-second
117
+ budget and at most three attempts. While disconnected, the current page and its
118
+ mounted state remain visible. A newer navigation cancels the older attempt.
119
+ Reconnection issues a fresh request with the current cookies; it does not serve
120
+ a saved private response. Application errors and deployment mismatches retain
121
+ their existing handling. Speculative prefetches are not queued offline.
122
+
123
+ For an optional application-owned connection indicator:
124
+
125
+ ```tsx
126
+ 'use client';
127
+ import { useOffline } from '@thomas.f/prnext/offline';
128
+
129
+ export default function ConnectionStatus() {
130
+ const offline = useOffline();
131
+ return offline ? <p role="status">Waiting for a connection…</p> : null;
132
+ }
133
+ ```
134
+
135
+ The hook reports browser offline status and pending navigation recovery, not a
136
+ guarantee that a server is reachable. Exhausted network recovery preserves the
137
+ page and dispatches `prnext:navigation-error` on `window`, with `detail.message`
138
+ for an application-owned retry notice. This recovery applies to App navigation;
139
+ it does not add offline Pages routing, a service worker or persistent storage.
140
+
141
+ Server Actions and other POSTs are **never automatically replayed**. If a mutation
142
+ loses its response, it may already have run: keep the user's input and verify its
143
+ result before offering an explicit retry. A full reload still loses ordinary
144
+ in-memory state; persist drafts deliberately if they must survive reloads.
145
+
146
+ With `typedRoutes: true`, `prnext typegen` writes a discovered route registry.
147
+ For the dynamic page above, this materializes an encoded URL:
148
+
149
+ ### `lib/product-url.ts`
150
+
151
+ ```ts
152
+ import { route } from '@thomas.f/prnext';
153
+
154
+ export const productUrl = route('/products/[slug]', { slug: 'blue mug' });
155
+ // /products/blue%20mug
156
+ ```
157
+
158
+ Pass catch-all parameters as arrays. The helper rejects missing/unknown
159
+ parameters, separators and dot segments. Add query strings through
160
+ `URLSearchParams`; do not embed query or fragment syntax in the route pattern.
161
+ Generated route checking is PRNext's registry, not the Next.js language-service
162
+ plugin.
163
+
164
+ ## Retained App pages
165
+
166
+ App layout branches retain inactive UI through React Activity. Effects stop
167
+ while hidden, and returning to an authorized destination restores its mounted
168
+ form state. The shared default budget is four inactive branches for two minutes,
169
+ not four at every nesting level. It is an entry/time limit, not a byte-level RAM
170
+ guarantee. It applies within a mounted layout; a new root layout loads a document.
171
+
172
+ ```js
173
+ export default {
174
+ navigationCache: { maxEntries: 3, ttlMs: 60000, authCookies: ['session'] },
175
+ };
176
+ ```
177
+
178
+ Use `navigationCache: false` to disable retention. Server Actions, `router.refresh()`
179
+ and observed cookie/authorization changes discard inactive branches while keeping
180
+ the current page's client state. Back/forward navigation requests fresh Flight
181
+ before revealing a retained destination. Cache hits do not bypass authorization.
182
+ After a custom authentication request outside Server Actions, call
183
+ `router.refresh()`. A browser integration may also dispatch
184
+ `window.dispatchEvent(new Event('prnext:invalidate-navigation'))` to refresh and
185
+ clear retained/prefetched state. This is in-memory UI retention, not offline
186
+ storage or mutation replay.
187
+
188
+ By default, cookie changes invalidate inactive branches while ordinary refresh
189
+ keeps the active component state. Set `authCookies` to the application's actual
190
+ session cookie names to also reset active branches when those credentials change.
191
+ Unrelated preference cookies then do not affect retention. Authorization headers
192
+ remain part of the identity. Identity is checked in each branch's authorized
193
+ request context, including restored parallel slots. In development, the private
194
+ identity key remains stable across Fast Refresh; build-time action-key rotation
195
+ does not discard the active editor state.
196
+
197
+ ## Route Handlers
198
+
199
+ An App Route Handler exports HTTP methods and returns a Web `Response` or
200
+ `NextResponse`.
201
+
202
+ ### `app/api/health/route.ts`
203
+
204
+ ```ts
205
+ export function GET() {
206
+ return Response.json({ ok: true });
207
+ }
208
+ ```
209
+
210
+ Read a body with `await request.json()` or `await request.formData()` in a
211
+ handler that accepts `request: Request`. Validate its shape and authorize access
212
+ before writing data. An App Route Handler is not a Pages `(req, res)` API handler.
213
+ The example uses the default Node runtime; do not opt into Edge without checking
214
+ all dependencies and the installed Edge restrictions.