@thomas.f/prnext 0.1.17-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 (137) hide show
  1. package/README.md +26 -869
  2. package/build/actions.mjs +1 -1
  3. package/build/analyze.mjs +180 -24
  4. package/build/app-config.mjs +13 -0
  5. package/build/app-static.mjs +34 -12
  6. package/build/app-styles.mjs +79 -0
  7. package/build/app.mjs +81 -26
  8. package/build/bundle-runtime.mjs +22 -9
  9. package/build/cache-components.mjs +1 -1
  10. package/build/cache-handlers.mjs +1 -1
  11. package/build/compact-css.mjs +53 -0
  12. package/build/compilation-cache.mjs +269 -0
  13. package/build/compilation-store.mjs +142 -0
  14. package/build/compiler.mjs +31 -8
  15. package/build/config.mjs +30 -1
  16. package/build/create.mjs +239 -0
  17. package/build/css-modules.mjs +56 -12
  18. package/build/deployment-assets.mjs +89 -0
  19. package/build/deployment-config.mjs +18 -0
  20. package/build/dev-css-update.mjs +4 -2
  21. package/build/dev-dependencies.mjs +1 -1
  22. package/build/dev-discovery.mjs +3 -3
  23. package/build/dev.mjs +15 -8
  24. package/build/dynamic.mjs +1 -1
  25. package/build/edge.mjs +3 -3
  26. package/build/fonts.mjs +1 -1
  27. package/build/framework-imports.mjs +15 -5
  28. package/build/html-only-config.mjs +53 -0
  29. package/build/html-only-graph.mjs +67 -0
  30. package/build/index.mjs +59 -26
  31. package/build/instrumentation.mjs +30 -0
  32. package/build/metadata-routes.mjs +1 -1
  33. package/build/migration-audit.mjs +1 -1
  34. package/build/native-type-config.mjs +37 -0
  35. package/build/persistent-cache.mjs +18 -3
  36. package/build/precompress.mjs +1 -1
  37. package/build/prerender-cache.mjs +70 -0
  38. package/build/prerender-config.mjs +29 -0
  39. package/build/prerender-pages.mjs +19 -9
  40. package/build/prerender-pool.mjs +165 -0
  41. package/build/prerender-process-worker.mjs +58 -0
  42. package/build/prerender-worker.mjs +5 -5
  43. package/build/production-builder.mjs +58 -9
  44. package/build/react-compiler-report.mjs +225 -0
  45. package/build/react-compiler.mjs +139 -0
  46. package/build/runtime-contract.mjs +2 -2
  47. package/build/static-export.mjs +4 -4
  48. package/build/styles.mjs +6 -4
  49. package/build/transform.mjs +1 -1
  50. package/build/typed-routes.mjs +4 -0
  51. package/build/typescript-dev.mjs +35 -8
  52. package/build/typescript-native-worker.mjs +55 -0
  53. package/build/typescript-native.mjs +18 -0
  54. package/build/typescript-toolchain.mjs +19 -0
  55. package/build/typescript.mjs +6 -4
  56. package/build/webpack-graph.mjs +6 -3
  57. package/build/worker-memory.mjs +9 -0
  58. package/cli.mjs +60 -4
  59. package/compat/activity-cache.cjs +26 -0
  60. package/compat/after.cjs +6 -4
  61. package/compat/app-layout-context.cjs +52 -2
  62. package/compat/base64.cjs +10 -0
  63. package/compat/cache-handlers.cjs +12 -2
  64. package/compat/cache-wire.cjs +28 -0
  65. package/compat/cache.cjs +2 -1
  66. package/compat/cache.d.cts +4 -0
  67. package/compat/cookies.cjs +21 -5
  68. package/compat/data-cache.cjs +12 -8
  69. package/compat/flight-delta.cjs +150 -0
  70. package/compat/headers.cjs +4 -2
  71. package/compat/incremental-cache.cjs +20 -7
  72. package/compat/index.d.ts +68 -3
  73. package/compat/link.cjs +12 -9
  74. package/compat/navigation-authorization.cjs +9 -0
  75. package/compat/navigation-stages.cjs +19 -0
  76. package/compat/offline-store.cjs +11 -0
  77. package/compat/offline.cjs +5 -0
  78. package/compat/offline.d.cts +2 -0
  79. package/compat/redis-cache.cjs +201 -0
  80. package/compat/redis-cache.d.cts +37 -0
  81. package/compat/server-primitives.cjs +31 -11
  82. package/compat/server.d.cts +15 -2
  83. package/compat/static-generation.cjs +7 -0
  84. package/compat/use-cache.cjs +3 -0
  85. package/docs/ai/compatibility.md +171 -2
  86. package/docs/ai/data.md +165 -5
  87. package/docs/ai/deployment.md +158 -0
  88. package/docs/ai/quickstart.md +29 -4
  89. package/docs/ai/routing.md +82 -0
  90. package/docs/ai/troubleshooting.md +37 -2
  91. package/package.json +26 -7
  92. package/runtime/action-client.mjs +10 -4
  93. package/runtime/action-server.mjs +2 -0
  94. package/runtime/app-client.mjs +212 -65
  95. package/runtime/app-content.mjs +4 -3
  96. package/runtime/app-partial-client.mjs +3 -0
  97. package/runtime/app-partial.mjs +1 -1
  98. package/runtime/app-prefetch-constants.mjs +4 -0
  99. package/runtime/app-prefetch.mjs +2 -3
  100. package/runtime/app-render-key.mjs +5 -0
  101. package/runtime/app-render.mjs +88 -28
  102. package/runtime/app-routing.mjs +22 -9
  103. package/runtime/app-static.mjs +18 -8
  104. package/runtime/app-stream-html.mjs +10 -53
  105. package/runtime/app-style-selection.mjs +34 -0
  106. package/runtime/app-styles.mjs +154 -0
  107. package/runtime/cache-components-rsc.mjs +4 -1
  108. package/runtime/cache-request.mjs +2 -1
  109. package/runtime/deployment-client.mjs +19 -0
  110. package/runtime/dev-client.mjs +7 -2
  111. package/runtime/dev-compiler-broker.mjs +42 -0
  112. package/runtime/dev-indicator.mjs +8 -3
  113. package/runtime/dev-lazy-tool.mjs +16 -0
  114. package/runtime/development.mjs +29 -12
  115. package/runtime/document.mjs +1 -1
  116. package/runtime/edge.mjs +6 -5
  117. package/runtime/fetch-cache.mjs +10 -8
  118. package/runtime/flight-delta.mjs +50 -0
  119. package/runtime/flight-tap.mjs +28 -0
  120. package/runtime/html-only.mjs +27 -0
  121. package/runtime/http.mjs +2 -0
  122. package/runtime/incremental-cache.mjs +25 -4
  123. package/runtime/instrumentation.mjs +49 -0
  124. package/runtime/navigation-recovery.mjs +36 -0
  125. package/runtime/navigation.mjs +7 -0
  126. package/runtime/node-html-stream.mjs +47 -0
  127. package/runtime/pages-client.mjs +14 -7
  128. package/runtime/pages-navigation.mjs +48 -63
  129. package/runtime/prefetch-scheduler.mjs +110 -0
  130. package/runtime/profile.mjs +14 -0
  131. package/runtime/profiles.json +2 -2
  132. package/runtime/render.mjs +3 -0
  133. package/runtime/route-pattern.mjs +44 -0
  134. package/runtime/rsc-worker.mjs +34 -12
  135. package/runtime/trace.mjs +78 -0
  136. package/runtime/watch-project.mjs +19 -15
  137. package/runtime/worker.mjs +70 -26
package/README.md CHANGED
@@ -12,932 +12,89 @@
12
12
  <h1 align="center">PRNext</h1>
13
13
 
14
14
  <p align="center">
15
- <a href="https://www.npmjs.com/package/@thomas.f/prnext"><img src="https://img.shields.io/npm/v/%40thomas.f%2Fprnext/alpha?style=for-the-badge&amp;label=npm&amp;labelColor=161b22&amp;color=007ec6" alt="Current npm alpha version" height="28" align="absmiddle"></a> &nbsp;
16
- <a href="https://github.com/Lorkydey/PRNext/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Lorkydey/PRNext?style=for-the-badge&amp;label=license&amp;labelColor=161b22&amp;color=98d6ac" alt="MIT License" height="28" align="absmiddle"></a> &nbsp;
17
- <a href="https://x.com/PRNextdev"><img src="https://img.shields.io/badge/-%40PRNextdev-171717?style=for-the-badge&amp;logo=x&amp;logoColor=white" alt="Follow @PRNextdev on X" height="28" align="absmiddle"></a>
15
+ <a href="https://www.npmjs.com/package/@thomas.f/prnext"><img src="https://img.shields.io/npm/v/%40thomas.f%2Fprnext?style=for-the-badge&amp;label=npm&amp;labelColor=161b22&amp;color=007ec6" alt="npm version"></a>
16
+ <a href="https://github.com/Lorkydey/PRNext/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Lorkydey/PRNext?style=for-the-badge&amp;labelColor=161b22&amp;color=98d6ac" alt="MIT License"></a>
18
17
  </p>
19
18
 
20
- A Rust-powered web runtime with React rendering on Node.js and a static adapter for completed browser builds.
19
+ A React framework with a Rust-powered runtime.
21
20
 
22
- > **Very early alpha.** Built for experimentation and feedback. Next.js compatibility is partial; expect bugs, missing features and breaking changes.
21
+ ## Install
23
22
 
24
- ## Documentation for AI assistants
25
-
26
- The npm package includes a short `AI.md` guide and focused
27
- documentation for setup, routing, data, migration, deployment and troubleshooting.
28
- Read the guidance for the version actually installed, without a network request
29
- or a native server:
30
-
31
- ```sh
32
- prnext docs --ai
33
- prnext docs --ai quickstart
34
- prnext docs --ai --list
35
- prnext docs --ai routing --json
36
- ```
37
-
38
- To help an assistant discover the guide, explicitly run
39
- `prnext docs --ai --init` in your application. This adds a short managed pointer
40
- to its `AGENTS.md`, preserving existing instructions. Installation does not edit
41
- your project. Assistants do not all discover dependency documentation on their own.
42
-
43
- ## Development
44
-
45
- Run `prnext dev` for requested-route compilation, React Fast Refresh, stylesheet
46
- updates and an error overlay. Links do not prefetch pages in development. Open
47
- browser tabs pin their routes; `onDemandEntries` controls inactive retention
48
- (default: five routes, 60 seconds, bounded to 64 inactive routes). Middleware,
49
- rewrites and parallel/intercepting routing conservatively compile the full graph.
50
- Shared layouts, error infrastructure and imported dependencies are still built.
51
-
52
- One Rust listener keeps its port and SSE connections open across saves. New
53
- render generations activate only after binding; old responses drain for up to
54
- 30 seconds. Three immutable asset generations remain available. This replaces
55
- render backends, rather than replacing arbitrary live Node modules in place.
56
- Compatible component/style edits preserve React hook state; config, environment,
57
- custom Document and incompatible module changes may reload the document.
58
-
59
- A round PRNext indicator opens compact developer tools at the bottom-left: live
60
- build/connection feedback, dismissed issues and page reload.
61
- Two short red arcs flag non-blocking TypeScript or recoverable hydration issues;
62
- a full red ring flags critical build or runtime errors. Recoverable hydration
63
- issues stay available under View issues without opening an overlay automatically.
64
- Opening the menu gathers the red indicator into a short stroke that follows the
65
- left edge of the controls to View issues, then draws its outline in place.
66
- Closing reverses the motion.
67
- Reduced-motion settings switch directly between states.
68
- Error details list the current issues above the selected diagnostic and mapped
69
- source. Copy for AI prepares all listed errors; Send to AI opens the selected
70
- error in the assistant workflow. Full messages and stack traces stay collapsible.
71
- Compilation keeps its blue loader; reduced-motion settings disable ring animation.
72
- Hide it until reload from the panel, or disable it with
73
- `devIndicators: false` without disabling error overlays or Fast Refresh.
74
- `devIndicators: { position: 'bottom-right' }` also accepts `bottom-left`,
75
- `top-left` and `top-right`. Drag the logo to snap it to any corner, or focus it
76
- and use Alt + arrow keys. The choice survives reloads in the current tab;
77
- changing the configured default resets it. The indicator is isolated from
78
- application styles and is not included in production browser bundles.
79
-
80
- The near-black menu grows from the logo as a connected bubble and retracts on
81
- close. Transitions reverse smoothly if interrupted, and reduced-motion settings
82
- show the same controls immediately.
83
-
84
- The indicator also opens a console with Browser/Server source filters, log levels, search, pause, clear
85
- and copy controls. Select a message to read or copy its complete captured text.
86
- Copy for AI prepares the visible logs with route context; its menu can copy all
87
- recorded errors, including those hidden by filters, with a correction prompt and
88
- repeated errors grouped. Query strings and fragments are omitted from route
89
- context. It captures browser console messages, uncaught errors and unhandled
90
- promise rejections while preserving native console output. Up to 500 messages
91
- and 2 Mi characters stay in memory in that page; individual messages retain up
92
- to 128,000 characters with an explicit truncation note beyond that limit. Values
93
- are text snapshots. A reload clears browser messages. Local tools stay on this
94
- machine unless you explicitly enable the Host AI relay described below.
95
-
96
- Inspect opens real browser/server requests, measured build and refresh timings,
97
- and a searchable route list. Compile a dynamic pathname on demand or invalidate
98
- its native page/data cache without clearing unrelated routes, restarting the dev
99
- generation or deleting persistent compiler caches. Cold routes and custom cache
100
- handlers report their limitations instead of claiming an invalidation occurred.
101
- Request details omit query strings, headers and bodies. Missing timings are
102
- shown as not measured; request time is not presented as a compiler benchmark.
103
-
104
- Errors resolve to original project source with a code frame and an editor link.
105
- Select a component first. If no assistant is connected, a compact connection
106
- dialog keeps your selection while you set up MCP. Sending unlocks after an
107
- assistant completes the MCP handshake; copying a configuration does not connect
108
- it. Connection settings then collapse. If it disconnects, your draft is preserved
109
- until you reconnect, and local component selection remains available.
110
- Client configuration opens smoothly, with a short scrollable code preview, full
111
- configuration copy and an optional setup guide for the selected assistant.
112
-
113
- Select element for AI captures its source marker, relevant styles and a bounded
114
- PNG of the selected DOM element. Screenshots exclude form controls and embedded
115
- frames; cross-origin assets can prevent capture. Sending queues context for the
116
- assistant to read through MCP; it does not start an idle assistant or claim a fix.
117
-
118
- ### AI development tools
119
-
120
- An assistant running locally can connect with the MCP stdio command below.
121
- Use the absolute project directory when the assistant has another working directory:
122
-
123
- ```sh
124
- prnext mcp /absolute/path/to/project
125
- ```
126
-
127
- The private discovery file is `.prnext-dev/tools.json`. The authenticated tool
128
- service binds only to loopback and exposes bounded project diagnostics, source
129
- excerpts, route compilation and native cache invalidation. It provides no shell
130
- or arbitrary file access. Browser diagnostics and capabilities are development-only.
131
-
132
- To reuse your existing PRNext Host MCP connection instead of configuring another
133
- MCP server, opt in from a terminal already logged into Host:
23
+ Run in your application directory:
134
24
 
135
25
  ```sh
136
- prnext login
137
- prnext dev --host-ai
26
+ npm i @thomas.f/prnext
138
27
  ```
139
28
 
140
- This requires the corresponding Host development-relay update. An older Host
141
- reports that the relay is unavailable while local development and local MCP keep
142
- working. The terminal pulls allowlisted requests from Host; it never uploads its
143
- localhost capability or exposes a public development URL. The existing AI
144
- connection's workspace, project permissions and revocation still apply. Host
145
- receives requested development diagnostics and explicitly queued context,
146
- including screenshots. An unlinked project requires an AI connection with access
147
- to all projects. Stopping dev closes the shared session; timed-out commands are
148
- not automatically replayed.
149
-
150
- The tools include `dev_snapshot`, `dev_logs`, `dev_routes`, `dev_route_ensure`,
151
- `dev_cache_invalidate`, `dev_source`, `dev_ai_context` and `dev_verify`.
152
- For a correction loop, read a snapshot, edit the source, then call `dev_verify`
153
- with that snapshot's `sequence` as `sinceSequence` and the pathname to check.
154
- Verification requires a newer successful generation and an open browser that
155
- actually applied that exact build. No new build or no browser evidence returns
156
- inconclusive. Reported compilation, TypeScript and browser errors fail the check;
157
- this observation does not replace application tests.
158
-
159
- The compact screen selector offers Desktop, Phone (390 × 844) and Tablet
160
- (768 × 1024), with width tooltips and a highlighted active mode. Previews use a
161
- separate, same-origin page with real CSS viewport dimensions, smooth device
162
- rotation and their own client console. A minimal dark toolbar controls the
163
- centered phone, tablet or desktop frame. Toggle Frame to hide the decoration without reloading; this
164
- choice also survives reloads in the tab. A side handle adjusts width by dragging
165
- or using the arrow keys. Compact hover and keyboard tooltips show device sizes
166
- and preview actions; Escape dismisses a tooltip while keeping the preview open.
167
- Phone and Tablet hide desktop scrollbars while keeping
168
- scrolling available; Desktop restores the application's scrollbar styles.
169
- Changing sizes preserves the preview's state; Desktop
170
- fills the available canvas and Close returns to the original page. This previews
171
- responsive layout, not a different user agent or touch hardware. Sites that block
172
- framing must use the browser's device tools instead.
173
-
174
- The pop-out icons open the console or device preview in separate windows. The
175
- console remains connected to its source, with its filters and copy controls;
176
- the dock icon brings it back. Device pop-outs keep their selected dimensions,
177
- orientation, frame preference and URL, but opening or docking them starts a fresh
178
- preview instance.
179
- Reloading or closing the source closes its tool windows. Desktop opens a normal,
180
- independent app window. The browser may require popups to be allowed for the site.
181
-
182
- Pure transforms persist in `.prnext-cache/transforms-dev-v1`, independently of
183
- production entries. The compiler also uses a private V8 cache, pruned at compiler
184
- startup toward 64 MiB / 2,048 files. Cache failure falls back to recomputation;
185
- `PRNEXT_BUILD_CACHE=0` disables PRNext's build/compiler caches. No application
186
- responses, module state or Server Action keys are reused.
187
-
188
- Loader cache corruption, unavailable storage and failed dependency snapshots
189
- are cache misses, not build failures. Loader execution errors still fail the
190
- build. Development Webpack sessions retain up to six compilers with bounded
191
- memory caches; configuration, environment and plugin identity changes invalidate
192
- them. Opaque recreated plugins may require a fresh compiler. Safe mode disposes
193
- these sessions; production Webpack builds remain one-shot.
194
- Map/Set and binary option values are compared explicitly; opaque configuration
195
- data uses a fresh compiler. Replace a plugin instance when an unchanged function
196
- captures external state that is invisible in its configuration.
197
-
198
- CSS-only updates rebuild the bundles whose recorded dependencies changed and
199
- retain other stylesheet URLs. Changed CSS Module exports still require a full
200
- build. Large HMR dependency graphs use compact, bounded control frames and an
201
- atomic commit; capacity failures report a diagnostic and use complete refreshes.
202
-
203
- Pages data functions run on request, including `fallback: false` validation.
204
- Offline HTML prerendering and gzip/Brotli generation remain production-only.
205
-
206
- CSS uses native Rust-based Lightning CSS by default, with the project's
207
- Browserslist targets. Custom PostCSS configurations, including Tailwind, keep their
208
- plugin pipeline. `cssEngine: 'postcss'` selects the previous default pipeline;
209
- `'lightningcss'` requests the native defaults but still respects a custom pipeline.
210
- Sass compilation, CSS Modules and relative asset rebasing remain supported.
211
-
212
- With an existing `tsconfig.json` and application-installed TypeScript, a separate
213
- watch process reports semantic errors in the overlay without blocking serving.
214
- It emits no application JavaScript. `typescript: {devChecks: false}` disables
215
- this watcher. Its incremental metadata lives in the private project cache.
216
-
217
- Enable `typedRoutes: true` to generate route suggestions and check literal links,
218
- router navigation and parameter objects. PRNext maintains
219
- `.prnext-types/routes.d.ts`, references it from `prnext-env.d.ts`, and adds that
220
- helper to the selected tsconfig's roots while preserving its JSONC comments and
221
- existing/inherited roots. Missing `next` / `next/*` TypeScript aliases are bound
222
- to PRNext declarations; existing aliases stay authoritative. Route additions/removals
223
- refresh the declarations.
224
- For dynamic paths, use the encoded route helper:
225
-
226
- ```ts
227
- import {route} from '@thomas.f/prnext';
228
- router.push(route('/users/[id]', {id: 'alice'}));
229
- ```
230
-
231
- This is PRNext's route registry, not the Next.js TypeScript language-service plugin.
232
- Keep generated `.prnext-types/`, `.prnext-dev/` and `.prnext-cache/` out of Git.
233
-
234
- Generate declarations and check types independently of application compilation:
235
-
236
- ```sh
237
- prnext check --json
238
- prnext typegen --json
239
- prnext typecheck --json
240
- ```
241
-
242
- `check` reports configuration, routes, React, TypeScript, supported Node and
243
- native installation diagnostics without installing or compiling anything.
244
- `typegen` and `typecheck` require application-installed TypeScript and an
245
- existing tsconfig, including `typescript.tsconfigPath`. They generate route
246
- declarations unless `typedRoutes: false`, report changes to the selected tsconfig
247
- and `prnext-env.d.ts`, and preserve JSONC comments and inherited settings.
248
- `typecheck` fails real type errors even with `ignoreBuildErrors: true`.
29
+ Node.js **22.23.4+, 24.22.1+ or 26.12.1+**. Windows, macOS and Linux (glibc), x64 and ARM64. No Rust installation needed.
249
30
 
250
- ## Production build tools
31
+ **Experimental alpha.** Next.js compatibility is partial.
251
32
 
252
- `prnext build --watch` retains bounded compiler graphs and rebuilds production
253
- output on source changes. It does not serve the application. Ordinary one-shot
254
- builds keep using the persistent transformation cache. Each incremental build
255
- uses fresh Server Action keys and an isolated prerender process. Configuration,
256
- lockfile and environment-file changes recycle the watch compiler. Stop with Ctrl+C.
33
+ ## Create a project
257
34
 
258
- Integrations can use `const builder = await createBuilder(root)` from
259
- `@thomas.f/prnext`, call `await builder.build()` after changes, and always finish
260
- with `await builder.dispose()`.
35
+ The `create` command requires PRNext 0.1.18-alpha or later.
261
36
 
262
37
  ```sh
263
- prnext analyze
264
- prnext analyze --json
265
- prnext analyze --max-js 150
266
- prnext analyze --baseline ./baseline.json --metric brotli --max-increase-percent 5
267
- prnext analyze --metric gzip --budgets ./bundle-budgets.json --json
38
+ npx @thomas.f/prnext create my-app
39
+ cd my-app
40
+ npm run dev
268
41
  ```
269
42
 
270
- The default metric is raw JavaScript. `--metric raw|gzip|brotli` selects the
271
- budget and comparison metric. `--max-js` is decimal kB per route;
272
- `--max-increase-bytes` and `--max-increase-percent` limit growth against
273
- `--baseline` (a saved build-analysis.json) or the previous build.
274
- Per-route JSON budgets map exact patterns to those same limits, for example
275
- `{"/": {"maxJs": 150, "maxIncreasePercent": 5}}`. Missing baseline routes fail
276
- regression budgets instead of silently passing. Budget failures exit 1; invalid
277
- arguments or analysis inputs exit 2. Reports include gzip/Brotli sizes, the
278
- largest modules and previous-build changes. Shared chunks are counted once per route; statically
279
- reachable App client boundaries are included. Conditional boundaries can
280
- exaggerate actual traffic; arbitrary dynamic imports, CSS, fonts and images are
281
- excluded. This covers React builds, not imported static HTML. Analysis files stay
282
- in the private build root, outside public assets.
283
-
284
- Optional startup module preloading in `prnext.config.mjs`:
285
-
286
- ```js
287
- export default {
288
- workerPreload: { routes: ['/', '/api/health'], maxRssMb: 256, timeoutMs: 5000 },
289
- };
290
- ```
291
-
292
- This initializes one render host and, when needed, its RSC isolate before accepting
293
- traffic. Choose up to 16 existing Node route patterns; Edge is unsupported. No
294
- page render, data hook, action or API handler is invoked. Module initialization
295
- does execute, including import side effects. RSS is a soft threshold between
296
- imports, not a hard process cap; a single import can exceed it. Worker retirement
297
- still applies. Failed/timed-out preloading is logged; ordinary requests can retry.
298
-
299
- Persistent replacements retain their previous process for 15 seconds after a
300
- successful traffic switch. A crash or three consecutive failed health probes
301
- triggers rollback if the previous process is still healthy. Configure this with
302
- `pstart --rollback-window 30000`, or `0` to disable (maximum 120000 milliseconds).
303
- `pstatus --json` shows the window and rollback reason. Manual stop cancels
304
- monitoring. Both processes consume memory during this window; rollback does not
305
- undo database changes, shared assets, dependency changes or external side effects.
306
-
307
- HTTP/1 WebSockets tunnel through external HTTP(S) rewrites, `pstart` and
308
- `prnext host`, with streaming/backpressure and lifetime accounting. The upstream
309
- must implement WebSockets; Pages/App handlers do not gain a WebSocket server API.
310
- Other protocols, CONNECT and incomplete handshakes are rejected. Active tunnels
311
- protect a host from idle retirement; persistent drain deadlines close remaining
312
- tunnels. Payloads are not buffered in full or replayed.
313
-
314
- ## Install & upgrade
315
-
316
- Node.js **22.23.4+, 24.22.1+ or 26.12.1+** · Windows, macOS and Linux glibc · x64 and ARM64
43
+ TypeScript by default. Add `--js` for JavaScript.
317
44
 
318
45
  <details>
319
- <summary><strong>Install · migrate an existing Next.js app</strong></summary>
46
+ <summary><strong>Use an existing Next.js app</strong></summary>
320
47
 
321
- Run these commands from your application directory. The current alpha requires matching React, React DOM and React Server Components versions:
48
+ Preview changes with `npx --no-install prnext migrate --dry-run`. Review the output, then run:
322
49
 
323
50
  ```sh
324
- npm install @thomas.f/prnext@alpha react@19.3.1 react-dom@19.3.1 react-server-dom-webpack@19.3.1
325
- npx --no-install prnext migrate --dry-run
326
51
  npx --no-install prnext migrate
327
52
  npx --no-install prnext check
328
53
  npx --no-install prnext dev
329
54
  ```
330
55
 
331
- Review the dry run before applying migration. Migration backs up your package files and keeps Next.js and your application source. Compatibility checks help find issues; they do not guarantee that every Next.js feature works.
332
-
333
- Migration detects npm, pnpm and Yarn Classic/Berry from the declared manager and
334
- lockfiles, and installs from the owning workspace root. Only the selected app
335
- manifest is migrated; Yarn may resolve the shared dependency graph. Conflicting
336
- managers, unlisted workspace packages and unsafe filesystem entries block
337
- automatic installation; `--no-install` prepares the manifest for manual review.
338
- Failures restore saved manifests and lockfiles when safe. Dependency directories
339
- and manager caches can contain partial installation results and are not rolled
340
- back. No global manager installation or forced peer-dependency bypass is used.
341
-
342
- Install only `@thomas.f/prnext`. Keep optional dependencies enabled: npm installs the matching native component automatically. Rust is not required to use a published release.
343
-
344
- `reactCompiler: false` is supported; enabling React Compiler still fails explicitly.
345
- `typedRoutes: true` enables PRNext's generated route declarations (see Development).
346
-
347
- The current source candidate also supports `devIndicators: false`, configured
348
- `experimental.optimizePackageImports` for pure ESM barrels with `sideEffects: false`,
349
- and App Router `maxDuration` values from 1 to 300 seconds. Import optimization
350
- preserves client/server boundaries and falls back to normal bundling when a barrel
351
- cannot be safely expanded. Duplicate App convention files follow `pageExtensions`
352
- priority and emit a warning. Identical public/App metadata files are accepted;
353
- conflicting content still fails explicitly. Route Handlers can call shared
354
- `use server` functions directly; pages retain their Flight/Server Action
355
- registrations. Mixed npm component exports preserve the real React server
356
- instance without requiring unused client hooks to exist in that environment.
357
-
358
- Node Route Handlers and Server Actions can use `after()` from `next/server`. Callbacks run after the
359
- response finishes or disconnects, including error responses, and retain their
360
- request context. Tracked work prevents idle worker retirement without blocking the
361
- next HTTP request. There are at most 128 tasks per request, within `maxDuration`
362
- (25 seconds by default, including the response's running time). Cookie reads are supported;
363
- post-response cookie writes are rejected. Server Actions wait for the HTTP response
364
- to finish, not just their intermediate Flight render. Server Component and Edge
365
- `after()` lifecycles are not implemented and fail explicitly. `revalidateTag`,
366
- `revalidatePath` and `updateTag` are also rejected inside an `after()` callback;
367
- perform supported invalidation in the Route Handler or Server Action before
368
- returning. This differs from the full Next.js lifecycle. During service shutdown,
369
- the 30-second standalone drain (35 seconds for global Host shutdown) can shorten a route's larger `maxDuration`. Ordinary sleep/eviction instead allows a 300-second drain. Forced
370
- termination, a memory-budget violation or a machine failure can still interrupt
371
- work; use durable external job storage for tasks that must survive these events.
372
-
373
- `experimental.proxyClientMaxBodySize` accepts a byte count or a size such as
374
- `'25mb'`, up to 32 MiB (default 10 MiB). Like Next's body clone, overflow retains
375
- only complete chunks before the limit and warns; a chunk crossing the limit is
376
- discarded. General request ingress remains capped at 32 MiB and Server Actions at
377
- 8 MiB. PostgreSQL's `pg` stays external by default so its optional native driver
378
- remains lazy; explicitly putting `pg` in `transpilePackages` opts out.
379
-
380
- The unreleased 0.1.17 candidate also persists pure transformations and
381
- prepared runtime bundles under `.prnext-cache`. Cache keys include framework and
382
- tool versions, source/options, project dependencies and environment fingerprints.
383
- Corrupt entries are discarded; builds still generate fresh manifests and Server
384
- Action registrations. `PRNEXT_BUILD_CACHE=0` disables these two caches.
385
-
386
- Node workers use `.prnext-cache/node-compile-v1` for V8 bytecode, with startup
387
- pruning toward 128 MiB / 4,096 files. This caches compilation, never module globals
388
- or page responses; it is not a filesystem quota.
389
- `PRNEXT_WORKER_COMPILE_CACHE=0` opts out; explicit `NODE_COMPILE_CACHE` and
390
- `NODE_DISABLE_COMPILE_CACHE` settings take precedence. Cache directories contain
391
- private compiled code: keep `.prnext-cache` out of source control and public roots.
392
- Deleting them is safe when no build or worker is using the project.
393
-
394
- Immutable HTML and browser assets now receive validated `.br` and `.gz` sidecars
395
- when compression saves bytes. Rust serves the negotiated representation directly;
396
- mutable public files and dynamic responses are not Brotli-precompressed.
397
- `pstart` uses one shared Rust HTTP proxy per supervisor, keeping health checks,
398
- restart/stop recovery and logs in its existing Node lifecycle manager. HTTP/1
399
- WebSockets tunnel to configured upstreams; other protocol upgrades are rejected.
400
-
401
- Google font build inputs are cached under `.prnext-cache/fonts-v1` (64 MiB,
402
- 256 entries, verified content hashes). A warm cache permits offline rebuilding;
403
- a cold build still needs access to Google's font endpoints. Remove this cache to
404
- refresh downloaded font inputs. This does not cache dynamic page responses.
405
-
406
- Set `typescript: {}` to check an existing `tsconfig.json` during production builds
407
- using the application's installed TypeScript. `typescript.tsconfigPath` selects
408
- its configuration, including inherited aliases. `ignoreBuildErrors: true` skips
409
- that production gate. Omitting `typescript` keeps production transpile-only;
410
- development checks run independently in the background unless `devChecks: false`.
411
- Checks do not emit application files or install packages. Only opt-in typed route
412
- generation adds declarations and adjusts tsconfig roots as described above.
56
+ Read the [compatibility guide](https://github.com/Lorkydey/PRNext/blob/main/packages/prnext/docs/ai/compatibility.md) before migrating.
413
57
 
414
58
  </details>
415
59
 
416
60
  <details>
417
- <summary><strong>Upgrade · update an existing PRNext project</strong></summary>
418
-
419
- Stop your development or production process before changing dependencies. If you use `pstart`, follow the [persistent app upgrade guide](#upgrade-persistent-apps) first.
61
+ <summary><strong>Build for production</strong></summary>
420
62
 
421
63
  ```sh
422
- npm install @thomas.f/prnext@alpha react@19.3.1 react-dom@19.3.1 react-server-dom-webpack@19.3.1
423
- npx --no-install prnext --version
424
- npx --no-install prnext check
425
64
  npx --no-install prnext build
426
- ```
427
-
428
- Then restart your app with its usual command; for a foreground production server:
429
-
430
- ```sh
431
65
  npx --no-install prnext start
432
66
  ```
433
67
 
434
- This updates the existing `@thomas.f/prnext` dependency and its native component together. You do not need to migrate an already-migrated project again. Commit the updated package manifest and lockfile.
435
-
436
- Use `@alpha` to select the current alpha release. `latest` is a separate npm tag; a dependency already installed in a project does not change until you update it.
68
+ After upgrading PRNext, rebuild your app and restart it.
437
69
 
438
70
  </details>
439
71
 
440
72
  <details>
441
- <summary><strong>Build & run · development and production</strong></summary>
73
+ <summary><strong>Use with AI assistants</strong></summary>
442
74
 
443
- For development:
75
+ Read the guides included with your installed version:
444
76
 
445
77
  ```sh
446
- npx --no-install prnext dev
447
- ```
448
-
449
- For production:
450
-
451
- ```sh
452
- npx --no-install prnext build
453
- npx --no-install prnext start
454
- ```
455
-
456
- The portable command is `prnext`. The shortcut `prn` is available in compatible shells. On Windows 10 and Windows Server 2022, use `prnext`: [Windows reserves the name PRN](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file).
457
-
458
- </details>
459
-
460
- <details>
461
- <summary><strong>Runtime profiles · balanced, speed, memory and classic</strong></summary>
462
-
463
- Balanced is the default. Set a profile when starting the production server:
464
-
465
- | Profile | Command | Priority |
466
- | --- | --- | --- |
467
- | Balanced | `npx --no-install prnext start --profile balanced` | Memory, CPU and response times |
468
- | Speed | `npx --no-install prnext start --profile speed` | Throughput and responsiveness |
469
- | Memory | `npx --no-install prnext start --profile memory` | Lower memory usage |
470
- | Classic | `npx --no-install prnext start --profile classic` | Original runtime settings |
471
-
472
-
473
- Worker retirement can be configured in `next.config.mjs` (PRNext extension):
474
-
475
- ```js
476
- export default {
477
- workerRetirement: { idleSeconds: 300, laneIdleSeconds: 30, keepWarm: false },
478
- };
78
+ npx --no-install prnext docs --ai
479
79
  ```
480
80
 
481
- Values are resolved **per field**: CLI > process environment > built configuration > profile.
482
- The CLI options are `--worker-idle-seconds`, `--lane-idle-seconds`, and
483
- `--keep-warm [true|false]` (a bare flag means true). The corresponding environment
484
- variables are `PRNEXT_WORKER_IDLE_SECONDS`, `PRNEXT_LANE_IDLE_SECONDS`, and
485
- `PRNEXT_KEEP_WARM` (`true`/`false` or `1`/`0`). Seconds must be integers from 0 to
486
- 604800; invalid supplied values fail even when a higher-priority value exists.
487
- Configuration-file changes require a new build; CLI/environment changes require
488
- restarting the server.
489
-
490
- `idleSeconds: 0` disables host idle retirement. `laneIdleSeconds: 0` disables
491
- early retirement of surplus lanes; the host deadline still applies to those
492
- lanes. Set both to zero to disable all idle retirement. `keepWarm: true` overrides
493
- the resolved host deadline and retains one primary lane per used host, while
494
- surplus lanes still retire. It creates no workers or artificial requests before
495
- real traffic. To restore a shorter CLI deadline when a lower-priority source sets
496
- `keepWarm: true`, also pass `--keep-warm false`. Active requests across **all**
497
- lanes reset the host deadline; streams and tracked post-response work remain
498
- protected. Keeping a host warm trades retained memory for lower wake latency;
499
- it does not change the profile's response, buffer or V8 limits.
500
-
501
- New builds include `runtime-contract.json`, separately declaring transport and
502
- lifecycle versions and fingerprints of the runtime modules. `start` and
503
- `host --check` reject missing, incompatible, future or mixed dynamic runtimes
504
- before accepting traffic and print `prnext build <project>`. Rebuild and restart after
505
- updating PRNext. Keep the selected production build immutable while it is in
506
- use; this is a startup check, not a continuous file watcher. A copied metadata file cannot upgrade old runtime modules;
507
- `--worker` must remain inside the verified build runtime directory. This is
508
- artifact consistency checking, not a signature or a sandbox. Legacy builds
509
- without any worker routes or middleware can still serve files without Node.
510
- The multi-app `host` supervisor's whole-application `idleSeconds`/memory policy
511
- is separate: keeping a Node worker warm does not override application sleep,
512
- shutdown or resource-budget termination.
513
-
514
- `prnext start` sizes Tokio's blocking I/O pool to four times the larger of its
515
- runtime thread count and requested render workers (minimum 4, maximum 256).
516
- `PRNEXT_BLOCKING_THREADS=1..1024` explicitly overrides it. This bounds threads,
517
- not the number of incoming HTTP connections. Filesystem admission separately
518
- bounds submitted blocking work and file response bodies, including slow clients:
519
-
520
- | Environment variable | Default | Accepted range | Scope per server process |
521
- |---|---:|---:|---|
522
- | `PRNEXT_FILE_CONCURRENCY` | 64 | 1–4096 | File preparation and live file source bodies |
523
- | `PRNEXT_FILE_WORK_CONCURRENCY` | 16 | 1–1024 | Submitted static/path/cache helper tasks, queued or running |
524
- | `PRNEXT_FILE_QUEUE` | 128 | 0–4096 | Waiting callers at each admission gate; 0 rejects immediately |
525
- | `PRNEXT_FILE_WAIT_MS` | 2000 | 1–60000 | Maximum admission wait at each gate |
526
-
527
- Invalid values fail startup before listening. Full queues and admission timeouts
528
- return HTTP 503 with `Retry-After: 1` and `Cache-Control: no-store`. These deadlines
529
- apply to admission, not the duration of an accepted response. Cancelling a queued
530
- caller releases its slot. An already running filesystem operation keeps its
531
- permit until it settles, including a pending file read after a client disconnects;
532
- an operating-system call cannot be forcibly cancelled safely. Large file bodies
533
- use a one-frame channel with backpressure. Without an explicit whole-request
534
- timeout, no deadline cuts off an active stream.
535
- Their asynchronous open/read operations retain a file-response permit; they are
536
- not included in the helper-task queue counter. These controls are not a global
537
- limit on application or background I/O.
538
- The limits do not bound TCP/kernel buffers or all HTTP connections, and an
539
- unresponsive disk can occupy the bounded capacity until its operation returns.
540
- Pages cache lookups use the same bounded filesystem admission. Their overload
541
- follows the existing page-capacity 503 path, including Pages JSON requests;
542
- it does not invoke error-page generation or regenerate a valid cached page.
543
-
544
- File operations stay off the async runtime threads; HTTP validators, range
545
- handling and path confinement are unchanged. The multi-app supervisor retains
546
- its existing pool sizing because
547
- its long-lived child-output readers have different requirements.
548
-
549
- For local diagnosis only, `PRNEXT_METRICS_FILE=<path>` adds one observer thread
550
- and cumulative counters once per second (file wraps at 16 MiB). It reports
551
- Tokio threads, instrumented filesystem tasks/queues and worker events. Nested
552
- filesystem timings are wall time, not CPU, and must not be added together.
553
- `fileAdmission` and `fileWorkAdmission` report occupancy, peaks, submitted and
554
- released work, rejections, timeouts, cancelled waits and wait duration. Their
555
- `waitingHeaderBytes` estimate counts URI and header content only; it excludes
556
- allocation overhead, request objects, bodies and TCP/kernel buffers. Use process
557
- memory measurements for the total footprint. Metrics never initialize admission
558
- settings or override values selected at startup.
559
- `activeJobs` counts transport jobs in the shared worker pool;
560
- `queuedJobs` excludes HTTP callers waiting before transport admission.
561
- `laneIdleRetirements` includes release of a cancelled lane's retained host
562
- reference, so it is not a count of distinct TCP connections closed. Host starts
563
- and watchdog kills are separate events; RSC isolate restarts do not have an
564
- independent cumulative counter. Normal operation has no observer thread or
565
- sampling timer.
566
- `--inspect` additionally records Node startup, module and RSC initialization
567
- phases; use uninstrumented runs for throughput comparisons.
568
-
569
- `prnext inspect --json` also reports fixed request stages: admission, render
570
- start, request-body admission/read, worker queue/first byte/headers, HTTP headers,
571
- response body and total lifetime. Completed, failed, cancelled and timed-out
572
- samples are distinct; byte and concurrency budgets report occupancy, peaks and
573
- rejections. Stages overlap and are not CPU timings. Local OTLP export includes
574
- `prnext.request.stage.duration`; neither metric includes query strings, request
575
- headers or body content.
576
-
577
- `PRNEXT_QUEUE_WAIT_MS=1..3600000` sets the worker/body queue wait (default
578
- 30000 ms); render admission and start share one queue deadline.
579
- `PRNEXT_REQUEST_TIMEOUT_MS=0..3600000` optionally limits the whole HTTP lifetime,
580
- including upload, middleware and response consumption by the HTTP layer.
581
- The default 0 disables it. Expiry before headers returns 504; expiry after
582
- headers terminates the stream and releases its capacity, including when the
583
- consumer stops polling. This is not proof of delivery to a remote client.
584
- Completed responses do not cancel tracked `after()` or cache finalization work.
585
- Route `maxDuration` remains an independent render limit.
586
-
587
- Render workers start on demand. Idle connection lanes retire after 30 seconds in `memory` and legacy `compact`. `balanced` keeps each host's primary lane warm for 300 seconds and retires surplus lanes after 30 seconds; `speed` and `classic` keep primary lanes warm and retire surplus lanes after 30 seconds. Retirement waits on idle deadlines rather than polling. Active responses and streams retain their lanes, and tracked application work keeps its Node host available even after the last lane retires. New requests can reuse that host while cache finalization continues. Once the work settles, the existing heartbeat releases this retention within one second. Releasing idle workers lowers retained memory but adds worker startup and module loading to the next request.
588
-
589
- Client disconnections release response permits and close incomplete transport lanes while retaining a healthy shared Node process. A lane whose terminal frame was fully validated can be reused. App Router cancellation pressure pauses new admission until abandoned work settles, with bounded queues and the original request deadlines; it does not immediately terminate unrelated responses. Successful response completion ends the RSC response deadline, while cache writes remain tracked until settlement. During this post-response work only, a shared watchdog probes the RSC isolate every five seconds and retires it if an acknowledgement takes more than 30 seconds. This measures responsiveness, not the total duration of asynchronous cache work; no RSC watchdog timer runs when that work is absent. Existing limits on cancelled requests and other API or middleware background work still apply.
590
-
591
- Explicit disposal of a worker pool starts a separate graceful shutdown: tracked work has up to 30 seconds to drain before Rust terminates and reaps the process, including a blocked JavaScript event loop. This shutdown grace does not limit normal idle cache finalization. Arbitrary detached tasks are outside the tracked lifecycle; applications that rely on them or long-lived in-process state should use `speed` or `classic` to keep their primary host warm. Such tasks are still not preserved across shutdown or worker failure.
592
-
593
- Each profile keeps its own admission, buffering and idle policy. Limits below are per worker host; render starts and live responses are separate budgets.
594
-
595
- | Profile | Render starts | Live responses | API concurrency | Response buffer | Primary idle deadline |
596
- |---|---:|---:|---:|---:|---|
597
- | `balanced` | 16 | 32 | 256 | 4 MiB | 300 seconds |
598
- | `speed` | 32 | 128 | 512 | 16 MiB | Keep warm |
599
- | `memory` | 8 | 28 | 64 | 1 MiB | 30 seconds |
600
- | `classic` | 16 | 32 | 512 | 8 MiB | Keep warm |
601
-
602
- On Linux with Node's `process.execve` available (Node 22.15+/23.11+), production `prnext start` replaces its CLI process with the native server. This removes a resident Node launcher from every profile without shrinking render or response budgets. Rust handles SIGINT, SIGTERM and SIGHUP gracefully; Linux also kills Node workers if their native parent dies, including when JavaScript is blocked. Explicit `--shutdown-on-stdin-eof` remains supported. Windows, macOS, older Node versions, IPC callers and Node instrumentation keep the supervised launch path. Only heap-sizing Node flags are eligible for replacement; other flags and `NODE_V8_COVERAGE` conservatively retain supervision. Node still labels `process.execve` experimental. This change does not remove the supervisors used by `pstart`, or change `host` and development mode.
603
-
604
- `balanced` keeps its 4 MiB V8 semi-space without `--optimize-for-size`. `speed` keeps its 16 MiB semi-space, larger concurrency and buffers, and warm hosts. `memory` keeps V8's size policy and early retirement; `classic` preserves its original V8 settings. Node heap flags can take precedence over the RSC isolate's young-generation resource limit: these settings are not total RSS caps. The earlier Windows V6 validation includes three 30-second measurements per scenario and a one-hour mixed endurance run; it predates this launcher change and is not an endurance result for this candidate. Workload and platform affect the CPU/RSS trade-off; a comparable Linux Nginx benchmark remains pending.
605
-
606
- An explicit `NODE_OPTIONS="--max-semi-space-size=4"` (including Node's underscore spelling) overrides the profile's nursery policy. PRNext also omits `--optimize-for-size` in that case: on Node 24.19.0, V8 otherwise replaces the explicit value with 1 MiB. This opts out of V8's broader size policy as well, so CPU and memory consumption can change; measure the chosen value for your workload. It does not add an old-generation heap limit or change the profile's admission, response buffers or idle retirement. Without an explicit override, PRNext uses the defaults of the selected profile.
607
-
608
- The V6 multi-application campaign keeps `start` on `balanced` and `host` on
609
- `memory`. With one shared CPU on Windows, `memory` completed both short trials
610
- at four applications / 512 MiB and eight applications / 1 GiB without allocation
611
- limit events. Its one-hour validation used four applications / 1 GiB, not those
612
- lowest budgets: 1,626,564 useful responses and 960 intentional cancellations,
613
- with no HTTP or validation errors. `balanced` gave lower neighbouring-application
614
- tail latency when the larger memory budget was available. These are independent
615
- `start` instances, not a benchmark of the hosting proxy. Windows commit limits,
616
- an active pagefile and process RSS sums are not Linux cgroup/PSS measurements;
617
- equivalent Linux density and endurance measurements remain pending. The local V6 report retains failures,
618
- variability and the small-static throughput cost of bounded admission.
619
-
620
- The filesystem work limit remains 16, the setting validated under overload and
621
- throughout the final endurance run. An explicit `PRNEXT_FILE_WORK_CONCURRENCY=64`
622
- improved small-file throughput by about 5% in two short configuration trials,
623
- but allows four times as many submitted helper tasks. It has not received the
624
- same endurance validation and is not a universal profile improvement.
625
-
626
- Results depend on your workload; see the [benchmark and its methodology](#early-benchmarks-against-nextjs).
627
-
628
- </details>
629
-
630
- ## Early benchmarks against Next.js
631
-
632
- Dynamic streaming with 128 concurrent clients and a deterministic local backend delayed by 40 ms:
633
-
634
- | Configuration | RAM | CPU load¹ | CPU/response | Throughput |
635
- |---|---:|---:|---:|---:|
636
- | Next.js | 605 MiB | 164% | 2.442 ms | 673 req/s |
637
- | **Balanced** | **207 MiB** | 124% | 1.704 ms | 726 req/s |
638
- | **Speed** | 496 MiB | 250% | **0.926 ms** | **2,698 req/s** |
639
- | **Memory** | **179 MiB** | **75%** | 2.067 ms | 362 req/s |
640
- | **Classic** | 303 MiB | 90% | 1.241 ms | 723 req/s |
641
-
642
- <details>
643
- <summary><strong>Benchmark methodology & trade-offs</strong></summary>
644
-
645
- ¹ 100% CPU = one fully utilized CPU core. RAM is measured under load.
646
-
647
- Measured September 27, 2026, on Apple M4 against Next.js 15.5.12. Values are medians of three six-second runs using identical application sources. This table covers one streaming scenario, not an overall average or guaranteed gains. Functional parity was checked before benchmarking.
648
-
649
- Under concurrent streaming, `memory` used 179 MiB versus 207 MiB for `balanced`, but served 362 versus 726 responses/s. On concurrent SSR, it used slightly more memory than `balanced`. The lowest-memory profile is workload-dependent.
650
-
651
- </details>
652
-
653
- ## Guides
654
-
655
- ### Build adapters
656
-
657
- Plain HTML/CSS/JavaScript sites need no package.json or React source tree:
658
-
659
- ```sh
660
- prnext build ./my-site
661
- prnext start ./my-site
662
- ```
663
-
664
- An `index.html` at the project root is detected automatically. Explicitly select
665
- it with `prnext build --adapter static --from .`. Root mode copies browser asset
666
- extensions only; it omits dotfiles, npm metadata, JSON data, source/server folders,
667
- configuration and server scripts. Put additional public data in a dedicated output
668
- directory and import it with `--from`; do not put secrets in browser assets.
669
-
670
- After running another builder, `prnext build --adapter auto` finds a completed
671
- `dist`, `build`, `out` or `.output/public` directory. Multiple outputs require an
672
- explicit `--from` choice. This command never runs another builder or its config.
673
- Vite (including React, Vue, Svelte and Solid browser apps), Astro static output,
674
- SvelteKit with `adapter-static`, and Nuxt generated output can use the same static
675
- runtime. Keep each framework's server rendering and API routes out of the import.
676
- See [Vite deployment](https://vite.dev/guide/static-deploy.html),
677
- [Astro deployment](https://docs.astro.build/en/guides/deploy/),
678
- [SvelteKit static generation](https://svelte.dev/docs/kit/adapter-static), and
679
- [Nuxt deployment](https://nuxt.com/docs/4.x/getting-started/deployment).
680
-
681
- PRNext keeps its React/Next-convention build as the default. The source candidate
682
- also imports static browser builds produced by Vite or another framework:
683
-
684
- ```sh
685
- npm run build
686
- npx --no-install prnext build --adapter static --from dist --spa
687
- npx --no-install prnext start
688
- ```
689
-
690
- Use `--spa` only for client-side routing. Omit it for a multi-page site. PRNext
691
- imports the completed public files; it does not compile Vue/Svelte source or run
692
- another framework's SSR server. Static requests require no Node render worker.
693
- This adapter needs the updated native binary built from the same source candidate;
694
- it is not part of the previously published alpha package.
695
-
696
- Every new build writes a versioned `build-output.json`. Inspect it with
697
- `prnext output --json`. See the [adapter contract](packages/prnext/build/ADAPTERS.md)
698
- and [compatibility scope](https://github.com/Lorkydey/PRNext/blob/main/COMPATIBILITY.md) for supported inputs and boundaries.
699
-
700
- <details>
701
- <summary><strong>Deploy to PRNext Cloud (local development)</strong></summary>
702
-
703
- ### Deploy to PRNext Cloud
704
-
705
- The local CLI now supports browser login and source deployments. This feature is
706
- not yet included in a published npm release or deployed to the public Cloud app.
707
-
708
- ```sh
709
- prn login
710
- prn deploy ./my-app
711
- prn update ./my-app
712
- prn whoami
713
- prn logout
714
- ```
715
-
716
- `prnext` accepts the same commands. Login opens the browser and reuses its session,
717
- or returns to terminal approval after web sign-in. Confirm the code shown in your
718
- terminal. `--no-browser` prints the URL for manual authorization.
719
-
720
- `deploy` creates an upload project and saves its link in the ignored
721
- `.prnext-cloud/project.json`; `update` sends changes to that same project.
722
- `deploy --project ID` links an existing upload project. `--dry-run` lists source
723
- files without connecting or uploading; `--no-wait` returns after queueing.
724
- `--timeout SECONDS` controls waiting (default 600). After interruption or
725
- `--no-wait`, `update` resumes the recorded request first; run it again to deploy
726
- further changes. Server-side request IDs prevent duplicate queued builds.
727
-
728
- Archives exclude `.env*`, credentials, `node_modules`, `.git`, generated
729
- `.next`/`.prnext*` output and `.local`. Root `.gitignore` and `.prnextignore`
730
- support additional glob exclusions and `!` rules; nested/global Git ignore files
731
- are not read. Mandatory exclusions cannot be re-included. Nonexcluded symbolic
732
- links are refused. On a compatible Host server: 100 MiB ZIP, 500 MiB expanded,
733
- 15,000 files and 64 MiB per file. Transfers use resumable 4 MiB chunks on the VPS;
734
- legacy servers retain their 7 MiB upload limit. No object storage is required.
735
-
736
- When production `.env` files are detected, `deploy` and `update` ask before
737
- importing variables (default: no). `--with-env` explicitly opts in;
738
- `--without-env` skips the prompt. Noninteractive commands skip import unless
739
- `--with-env` is set. Variables travel through the encrypted environment API,
740
- never inside the source ZIP or project link. Matching remote keys are replaced;
741
- other keys remain. `NEXT_PUBLIC_` values may be exposed in the browser bundle.
742
- This feature requires the updated Host API and remains unpublished.
743
- Use project environment settings for secrets; inspect `--dry-run` for other
744
- sensitive files in your own source tree.
745
-
746
- Credentials stay under `~/.prnext/cloud/` (or private `PRNEXT_CLOUD_HOME`, outside
747
- the source directory). Tokens are scoped to project reads/uploads/deployments,
748
- expire after 30 days, and can be revoked with `logout` or in workspace settings.
749
- Browser sign-out does not revoke authorized terminals.
750
-
751
- For a local Cloud server, use `--server http://127.0.0.1:3003` or
752
- `PRNEXT_CLOUD_URL`. From this checkout, run
753
- `node packages/prnext/cli.mjs login --server http://127.0.0.1:3003`.
754
- Production defaults to `https://app.prnext.dev`; credentials are isolated by origin.
755
-
756
- A configured isolated Linux worker is required to deploy. A local Windows panel
757
- supports login and dry runs, but reports unavailable hosting explicitly.
758
- Approved offline dependencies, runtime network isolation and current Cloud quotas
759
- still apply; these commands do not bypass the hosting worker or configure DNS/TLS.
760
-
761
- </details>
762
-
763
-
764
- <details>
765
- <summary><strong>Check a migration before switching</strong></summary>
766
-
767
- ### Check a migration before switching
768
-
769
- ```sh
770
- prnext migrate ./my-app --check
771
- prnext migrate ./my-app --check --json
772
- prnext migrate ./my-app --check --against http://localhost:3000 --candidate http://localhost:3001 --routes paths.json
773
- ```
774
-
775
- The source audit reports unsupported Next imports with file and line numbers, client/server import conflicts, dependency versions and scripts requiring manual changes. It leaves sources, package files and builds untouched. Configuration files are evaluated by the existing preflight; installed dependencies and custom loaders still require a build. Warnings are distinct from blocking errors. A failed audit or response comparison exits with code 1.
776
-
777
- For comparison, start the existing Next application and the PRNext candidate separately. `paths.json` is a JSON array such as `["/", "/products/123", "/api/catalog"]`; without it, the command selects non-parameterized page routes from the audit. It sends GET requests without authentication, follows no redirects, and compares status, content type, redirect destinations and bodies. JSON object key order is ignored; HTML compares text with scripts/styles removed. This verifies response samples, not hydration, styling, interactive behavior or every dynamic path. Timing observations are not controlled performance benchmarks. `--timeout 10000` sets each response's deadline in milliseconds.
778
-
779
- </details>
780
-
781
- <details>
782
- <summary><strong>Inspect routes, cache and timings</strong></summary>
783
-
784
- ### Inspect routes, cache and timings
785
-
786
- ```sh
787
- prnext build ./my-app
788
- prnext start ./my-app --inspect
789
- # In another terminal, after visiting the application:
790
- prnext inspect ./my-app
791
- prnext inspect ./my-app --json
792
- prnext inspect ./my-app --otlp > metrics.json
793
- ```
794
-
795
- The inspector explains static, dynamic and partially prerendered routes using build metadata, including observed App prerendering bailouts and Pages data hooks. Opt-in measurements show native HTTP timings, fetch destinations and timings, native data cache hits/misses/stale reads, bypass reasons and successful tag/path invalidations. A custom cache handler is identified as a delegation; its internal hit rate is not inferred. Native page-file cache decisions and client router caching are not counted as data-cache hits.
796
-
797
- The summary adds sampled HTTP p50/p95, server errors, worker startup p95, current
798
- worker queue/activity and recent Node worker RSS. Missing or stale resource samples
799
- are shown as unavailable, never as zero. RSS excludes the native server; worker
800
- threads sharing a PID are counted once. `start --inspect` also enables bounded native
801
- counter snapshots. These opt-in diagnostics do not change normal serving defaults.
802
-
803
- `inspect --otlp` writes an OTLP/JSON Metrics payload for a bounded local sample.
804
- The custom `prnext.http.response.headers.duration` histogram uses seconds and stops
805
- at response headers, excluding streaming body time. It is deliberately not named
806
- `http.server.request.duration`. Samples can span sessions and overlap repeated
807
- exports; this is a diagnostic snapshot, not a continuous traffic or billing counter.
808
- No collector connection or public diagnostics endpoint is enabled automatically.
809
-
810
- Timings end when headers are ready, so streaming body time is excluded. Samples are bounded, can span process sessions, and are written under the app's `.prnext-cache/inspect` directory. Request bodies, headers, cookies, URL queries and credentials are omitted; runtime tag/path identifiers are hashed consistently. Logs retain at most 1 MiB per segment plus a previous segment, with old process sessions pruned. Under load, diagnostics may drop samples. `--inspect` also works with `prnext dev`; standalone/native launches can set `PRNEXT_INSPECT_DIR` explicitly. No public diagnostic endpoint is added.
811
-
812
- </details>
813
-
814
- <details>
815
- <summary><strong>Host several applications</strong></summary>
816
-
817
- ### Host several applications
818
-
819
- ```sh
820
- npm run build -- examples/basic
821
- npm run build -- examples/app
822
- node packages/prnext/cli.mjs host examples/hosting/prnext.host.json --check
823
- node packages/prnext/cli.mjs host examples/hosting/prnext.host.json
824
- # In another terminal:
825
- node packages/prnext/cli.mjs host examples/hosting/prnext.host.json --status
826
- ```
827
-
828
- The example routes `basic.localhost:8080` and `app.localhost:8080` to separate applications. Resolve those hostnames to the listener address, or supply their exact `Host` header when testing. Installed packages use `prnext host config.json`. Configuration roots are relative to the JSON file. Each app has a unique name, root and exact hostname list, with optional `memoryMb`, `idleSeconds`, `workers`, `profile`, `env` and `inspect` settings. `--status --json` reads the local status snapshot beside the configuration, including its age; it does not connect to a live admin endpoint. Restart the host to apply configuration or build changes.
829
-
830
- The native gateway keeps each application asleep until requested. A waking app reserves its configured memory budget; if capacity is full, inactive apps can release theirs, while busy requests receive 503 rather than starting an unbudgeted app. Requests and streaming responses hold their reservation until completion or cancellation. Idle apps begin stopping after `idleSeconds` and wake on the next request. Sleep and capacity eviction retain the memory reservation while the child drains supported `after()` and ISR work, allowing up to 300 seconds plus five seconds for process cleanup. A wake waiting for that capacity can take longer. Status shows `draining` with the process still present; monitoring and memory-budget enforcement continue. Global Host shutdown shortens outstanding retirement to its own 35-second deadline. Persistent caches remain on disk; in-process state and untracked background jobs do not survive sleep. Apps receive their configured environment and a small platform environment allowlist, then load their own `.env` files.
831
-
832
- The watchdog samples the RSS of each app's native server and descendants about once per second. Exceeding `memoryMb` stops that process tree, can interrupt its in-flight requests, and imposes a 30-second cooldown. V8 also receives an initial heap guard unless the app config supplies `NODE_OPTIONS`. These are sampled operating budgets, not kernel-enforced hard limits; allow extra RAM for the gateway, the OS and sampling overshoot. Process separation isolates caches, environment and ordinary failures, but apps run as the same OS user: host only trusted applications. Use separate users or containers for untrusted tenants.
833
-
834
- The 0.1.12-alpha Windows host check used four applications sharing one CPU and a 1 GiB Job commit budget. Two 30-second mixed SSR/stream/API trials measured about 333 requests/s through `host` versus 361 directly with the same V8 heap guard (about 8% gateway cost in this fixture). The matching direct controls followed the host trials; these short runs are not a general capacity guarantee. Three sleep/resume cycles per trial used `idleSeconds: 3` to exercise retirement: 32 simultaneous arrivals completed in 1.92–2.35 seconds, with one startup per application and no failures. The default whole-app deadline remains 300 seconds. The gateway keeps its one-second status/RSS monitor running while apps sleep; idle CPU is not zero. No host endurance or Linux performance result is claimed.
835
-
836
- Hosting supports HTTP streaming and preserves the original application Host. HTTP/1 WebSockets tunnel to configured upstreams; other protocol upgrades are rejected. Put a TLS reverse proxy in front for public hosting; this command does not configure DNS, TLS, OS services or deploy to a VPS. Windows, macOS and Linux use the same JSON format and CLI.
837
-
838
- </details>
839
-
840
- <details>
841
- <summary><strong>Keep production apps running</strong></summary>
842
-
843
- ### Keep production apps running
844
-
845
- `prnext start` keeps its normal foreground behavior. Use the separate persistent commands when an app should survive closing the terminal:
846
-
847
- ```sh
848
- prnext build ./my-app
849
- prnext pstart ./my-app --name web --port 3000
850
- prnext pstatus
851
- prnext plogs web --follow
852
- # After rebuilding the app:
853
- prnext prestart web
854
- prnext pstop web
855
- ```
856
-
857
- `pstart` starts a detached supervisor and returns once the app passes its health check. Applications restart after a crash with increasing delays; ten failures within five minutes stop retries until `prestart`. A separate watchdog restarts the supervisor after a crash or an unresponsive event loop. Each app has a stable HTTP listener and its own native server and workers. This mode adds a shared Rust HTTP proxy and two supervisor processes; it does not enable the idle sleep or memory reservations of `prnext host`.
858
-
859
- `prestart` copies the current production build, starts a replacement on a private port, and sends a GET to `--health-path` (default `/`). A 2xx or 3xx response must arrive within `--health-timeout 15000` milliseconds. Only then does new traffic switch to the replacement. If startup or the health check fails, the existing healthy instance keeps serving. Existing HTTP streams can finish for up to `--drain-timeout 30000` milliseconds, after which remaining requests are closed. Choose a health route that checks the dependencies your application needs. Two generations temporarily use memory and disk space during replacement.
860
-
861
- Build copies live under the project's ignored `.prnext-persistent` directory and are removed after their processes stop. Rebuilding does not replace the active generation's compiled files. Project dependencies, `public` files and persistent caches remain shared; avoid changing dependencies or deleting public assets while old requests still need them. HTTP streaming, original Host headers and multiple cookies are preserved. HTTP/1 WebSockets tunnel to configured upstreams; other protocol upgrades are rejected. A supervisor crash can interrupt requests; health-checked replacement is not a guarantee against machine failures or incompatible application changes. A TLS reverse proxy can sit in front of the persistent listener.
862
-
863
- Available commands:
864
-
865
- | Command | Behavior |
866
- | --- | --- |
867
- | `prnext pstart [directory] --name NAME` | Start or restore an app; identical repeated starts are idempotent |
868
- | `prnext prestart [name] [--all]` | Load the current build through a health-checked replacement |
869
- | `prnext pstop [name] [--all]` | Stop apps and keep them stopped across supervisor restarts |
870
- | `prnext pdelete [name] [--all]` | Stop apps and remove their saved configuration; retain logs |
871
- | `prnext pstatus [name] [--json]` / `prnext plist` | Show status, PIDs, build IDs, starts and active requests |
872
- | `prnext plogs [name] --lines 100 --follow` | Read/tail app output; `--supervisor` selects supervisor logs |
873
- | `prnext pdown` | Stop the supervisor and apps, retaining enabled flags for their next launch |
874
- | `prnext pstartup [--remove]` | Enable/remove automatic restoration at user login |
875
-
876
- Without a name, `prestart`, `pstop`, `pdelete` and `plogs` select the app registered for the current directory. `pstart` accepts `--hostname`, `--port`, `--workers`, `--profile`, `--inspect`, `--health-path`, `--health-timeout` and `--drain-timeout`; see `prnext pstart --help`. Change saved listener/settings with `pdelete`, then `pstart`. Applications load their project `.env` files; arbitrary caller-shell variables and secrets are not copied into the saved registry. The state directory defaults to `~/.prnext/processes`; set `PRNEXT_PM_HOME` consistently for a separate supervisor. Keep that directory private: it contains local control credentials and application logs. Logs rotate at 10 MiB with three retained segments per app and for the supervisor. App output can contain whatever the application logs.
877
-
878
- `pstartup` is opt-in and enables restoration on the **next user login**. On Windows it registers a hidden scheduled task for the current account; on macOS it writes a user LaunchAgent; on Linux it enables a systemd user service. These definitions restart a failed watchdog once managed by the OS. Windows and macOS user startup do not run before login. A Linux administrator can enable user lingering separately for boot-time operation without an interactive login. No OS startup settings change just by running `pstart`, and the command does not install a Windows system service or alter other accounts. Run `pstartup` again after moving or upgrading Node or the PRNext package. Platform references: [Windows scheduled tasks](https://learn.microsoft.com/en-us/powershell/module/scheduledtasks/new-scheduledtasksettingsset), [Apple launch agents](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html), [systemd user lingering](https://www.freedesktop.org/software/systemd/man/252/loginctl.html).
879
-
880
- ### Upgrade persistent apps
881
-
882
- The supervisor may be shared by several projects. Use the same user and `PRNEXT_PM_HOME` throughout, and record the applications and their settings first:
883
-
884
- ```sh
885
- npx --no-install prnext pstatus --json
886
- ```
887
-
888
- Before changing package files, stop the apps and supervisor using the **old installation**. These commands affect **all apps managed by that supervisor**, so schedule the interruption accordingly:
889
-
890
- ```sh
891
- npx --no-install prnext pstop --all
892
- npx --no-install prnext pdown
893
- ```
894
-
895
- Install the update and rebuild each affected project as described under [Install & upgrade](#install--upgrade). Using the new CLI, restart each app with its original name, port and other options. For example:
896
-
897
- ```sh
898
- npx --no-install prnext pstart --name web --port 3000
899
- ```
900
-
901
- If the saved Node or native executable path changed, remove that app's saved entry with `prnext pdelete NAME`, then register it again with `prnext pstart` and its recorded options. This removes saved settings but retains logs. If login startup was enabled, re-run `prnext pstartup` to refresh its paths.
902
-
903
- `pdown` alone keeps apps enabled for restoration; stop them first to prevent an old configuration from restarting during the upgrade.
81
+ Run `npx --no-install prnext docs --ai --init` to add a guide reference to your project's `AGENTS.md`.
904
82
 
905
83
  </details>
906
84
 
907
85
  <details>
908
86
  <summary><strong>Develop from this repository</strong></summary>
909
87
 
910
- ### Develop from this repository
911
-
912
- Install Node.js 22+ and Rust with rustup, then run:
913
-
914
88
  ```sh
915
89
  npm ci
916
90
  npm run build:native
917
91
  npm run dev -- examples/app
918
92
  ```
919
93
 
920
- These commands also work in PowerShell and Command Prompt. On Windows, source builds require Visual Studio Build Tools with the Desktop development with C++ workload and a Windows SDK, plus NASM on x64. Rustup selects the repository's Rust 1.98 toolchain. Linux source builds need a C/C++ toolchain, NASM and pkg-config; macOS needs Xcode command line tools and NASM.
921
-
922
- For production locally, run `npm run build -- examples/app`, then `npm run start -- examples/app`. Standalone output runs with `node server.js` on its build OS and architecture, including Windows. Published native packages remove the Rust/C++ build requirement for consumers. Keep the framework and platform components on matching release versions.
923
-
924
- For source builds, `cargo build --release --locked --features gzip-zlib-rs` enables an experimental alternative gzip/deflate backend. Ubuntu x64 trials reduced JSON API CPU cost but increased cumulative streaming RSS, so this option is disabled by default. It also changes the Rust PNG/TIFF codecs; runtime profiles and Node heap settings remain unchanged. Compare CPU, response size and memory on your workload before choosing it.
94
+ Source builds require Rust 1.98 and native build tools: Visual Studio C++ tools and a Windows SDK on Windows, Xcode command line tools on macOS, or a C/C++ toolchain and pkg-config on Linux. Install NASM on macOS, Linux and Windows x64.
925
95
 
926
96
  </details>
927
97
 
928
- ## Contributing
929
-
930
- Read the [contribution guide](https://github.com/Lorkydey/PRNext/blob/main/CONTRIBUTING.md),
931
- [Code of Conduct](https://github.com/Lorkydey/PRNext/blob/main/CODE_OF_CONDUCT.md)
932
- and [security policy](https://github.com/Lorkydey/PRNext/blob/main/SECURITY.md).
933
-
934
- <details>
935
- <summary><strong>License & credits</strong></summary>
98
+ ## Documentation
936
99
 
937
- ### License and credits
938
-
939
- PRNext is licensed under the [MIT License](LICENSE), copyright © 2026 Thomas (Lorkydey). Commercial use, modification, and redistribution are permitted; keep the copyright and license notice when distributing copies or substantial portions of the software. Third-party components retain their own licenses.
940
-
941
- If PRNext helps your project, a credit such as **“PRNext by Thomas (Lorkydey)”** with a link to [prnext.dev](https://prnext.dev) would be appreciated. A public credit is optional, not an additional license condition.
942
-
943
- </details>
100
+ [Guides](https://github.com/Lorkydey/PRNext/blob/main/packages/prnext/AI.md) · [Releases](https://github.com/Lorkydey/PRNext/releases) · [Contributing](https://github.com/Lorkydey/PRNext/blob/main/CONTRIBUTING.md) · [MIT License](https://github.com/Lorkydey/PRNext/blob/main/LICENSE)