@thomas.f/prnext 0.1.16-alpha → 0.1.17-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.
- package/AI.md +63 -0
- package/README.md +384 -9
- package/build/ADAPTERS.md +27 -2
- package/build/actions.mjs +5 -0
- package/build/analyze.mjs +184 -0
- package/build/app-config.mjs +7 -8
- package/build/app-static.mjs +12 -7
- package/build/app.mjs +23 -10
- package/build/build-lock.mjs +6 -6
- package/build/bundle-runtime.mjs +20 -5
- package/build/check.mjs +56 -11
- package/build/compiler.mjs +25 -1
- package/build/concurrent.mjs +12 -0
- package/build/config.mjs +21 -13
- package/build/css-modules.mjs +15 -4
- package/build/dev-compiler-health.mjs +11 -0
- package/build/dev-css-update.mjs +83 -0
- package/build/dev-dependencies.mjs +44 -0
- package/build/dev-discovery.mjs +28 -0
- package/build/dev-worker.mjs +14 -5
- package/build/dev.mjs +55 -4
- package/build/edge.mjs +3 -2
- package/build/framework-imports.mjs +40 -0
- package/build/incremental.mjs +8 -4
- package/build/index.mjs +96 -101
- package/build/inspect.mjs +3 -0
- package/build/inspection-summary.mjs +37 -4
- package/build/loader-cache.mjs +53 -26
- package/build/metadata-routes.mjs +2 -3
- package/build/migrate.mjs +60 -57
- package/build/npm-packages.mjs +3 -18
- package/build/package-manager.mjs +308 -0
- package/build/persistent-cache.mjs +97 -0
- package/build/precompress.mjs +62 -30
- package/build/prerender-pages.mjs +90 -0
- package/build/prerender-worker.mjs +10 -0
- package/build/production-builder.mjs +80 -0
- package/build/scan.mjs +4 -4
- package/build/source-analysis.mjs +42 -0
- package/build/static-adapter.mjs +13 -5
- package/build/static-input.mjs +48 -0
- package/build/styles.mjs +15 -3
- package/build/transform-cache.mjs +37 -4
- package/build/type-command.mjs +41 -0
- package/build/typed-routes.mjs +91 -0
- package/build/typescript-dev-worker.mjs +18 -0
- package/build/typescript-dev.mjs +22 -0
- package/build/typescript-watch.mjs +22 -0
- package/build/typescript.mjs +5 -4
- package/build/webpack-graph.mjs +164 -27
- package/build/worker-preload.mjs +9 -0
- package/cli.mjs +105 -121
- package/compat/index.d.ts +21 -7
- package/compat/link.d.cts +4 -3
- package/compat/navigation.d.cts +4 -3
- package/compat/router.d.cts +4 -3
- package/compat/typed-route.d.cts +17 -0
- package/docs/ai/compatibility.md +106 -0
- package/docs/ai/data.md +128 -0
- package/docs/ai/deployment.md +111 -0
- package/docs/ai/manifest.json +11 -0
- package/docs/ai/quickstart.md +146 -0
- package/docs/ai/routing.md +132 -0
- package/docs/ai/troubleshooting.md +120 -0
- package/index.mjs +2 -0
- package/native/diagnostics.mjs +34 -0
- package/native/resolve.mjs +7 -2
- package/package.json +25 -7
- package/release/ai-docs.mjs +48 -0
- package/release/verify.mjs +2 -0
- package/runtime/ai-docs.mjs +202 -0
- package/runtime/app-client.mjs +17 -6
- package/runtime/app-render.mjs +12 -0
- package/runtime/cloud/archive.mjs +5 -6
- package/runtime/compile-cache.mjs +8 -0
- package/runtime/dev-ai-brands.mjs +26 -0
- package/runtime/dev-ai-style.mjs +99 -0
- package/runtime/dev-build-reasons.mjs +25 -0
- package/runtime/dev-cache-control.mjs +53 -0
- package/runtime/dev-client.mjs +239 -45
- package/runtime/dev-console-copy.mjs +19 -0
- package/runtime/dev-console.mjs +106 -0
- package/runtime/dev-dependency-graph.mjs +40 -0
- package/runtime/dev-element-picker-style.mjs +27 -0
- package/runtime/dev-element-picker.mjs +213 -0
- package/runtime/dev-error-overlay-style.mjs +41 -0
- package/runtime/dev-error-overlay.mjs +167 -0
- package/runtime/dev-error-report.mjs +121 -0
- package/runtime/dev-file-changes.mjs +1 -1
- package/runtime/dev-gateway.mjs +44 -0
- package/runtime/dev-host-relay.mjs +66 -0
- package/runtime/dev-indicator.mjs +186 -0
- package/runtime/dev-issue-motion.mjs +214 -0
- package/runtime/dev-lazy-tool.mjs +18 -0
- package/runtime/dev-logo.mjs +2 -0
- package/runtime/dev-notification.mjs +81 -0
- package/runtime/dev-popout.mjs +34 -0
- package/runtime/dev-position.mjs +107 -0
- package/runtime/dev-preview-touch.mjs +122 -0
- package/runtime/dev-runtime-pool.mjs +45 -0
- package/runtime/dev-runtime-spare.mjs +57 -0
- package/runtime/dev-tools-client.mjs +155 -0
- package/runtime/dev-tools-mcp.mjs +126 -0
- package/runtime/dev-tools-metrics.mjs +31 -0
- package/runtime/dev-tools-model.mjs +42 -0
- package/runtime/dev-tools-panel.mjs +341 -0
- package/runtime/dev-tools-result.mjs +37 -0
- package/runtime/dev-tools-server.mjs +256 -0
- package/runtime/dev-tools-source.mjs +104 -0
- package/runtime/dev-tooltip.mjs +94 -0
- package/runtime/dev-ui-icons.mjs +8 -0
- package/runtime/dev-workbench-style.mjs +106 -0
- package/runtime/dev-workbench.mjs +428 -0
- package/runtime/dev-worker-logs.mjs +31 -0
- package/runtime/development.mjs +307 -0
- package/runtime/env.mjs +2 -1
- package/runtime/pages-client.mjs +10 -1
- package/runtime/pages-navigation.mjs +6 -1
- package/runtime/persistent/client.mjs +6 -5
- package/runtime/persistent/daemon.mjs +66 -56
- package/runtime/persistent/native-proxy.mjs +63 -0
- package/runtime/preload.mjs +12 -0
- package/runtime/rsc-worker.mjs +7 -0
- package/runtime/typed-route.mjs +19 -0
- package/runtime/watch-project.mjs +12 -5
- package/runtime/worker.mjs +36 -2
package/docs/ai/data.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Request data, actions and caching
|
|
2
|
+
|
|
3
|
+
[AI documentation index](../../AI.md)
|
|
4
|
+
|
|
5
|
+
## Request context
|
|
6
|
+
|
|
7
|
+
Use server request APIs only while handling a PRNext request. Await `headers()`
|
|
8
|
+
and `cookies()` from `next/headers`. Headers are read-only; cookie writes belong
|
|
9
|
+
in a Server Action or Route Handler before response headers commit. Do not read
|
|
10
|
+
the current request at module initialization or stash request data in a
|
|
11
|
+
process-global variable.
|
|
12
|
+
|
|
13
|
+
The following complete example stores a non-sensitive display preference. It is
|
|
14
|
+
not an authentication or session implementation.
|
|
15
|
+
|
|
16
|
+
### `app/preferences/actions.ts`
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
'use server';
|
|
20
|
+
|
|
21
|
+
import { cookies } from 'next/headers';
|
|
22
|
+
import { revalidatePath } from 'next/cache';
|
|
23
|
+
|
|
24
|
+
export async function saveTheme(form: FormData) {
|
|
25
|
+
const theme = form.get('theme');
|
|
26
|
+
if (theme !== 'light' && theme !== 'dark') throw new Error('Invalid theme');
|
|
27
|
+
const store = await cookies();
|
|
28
|
+
store.set('theme', theme, { httpOnly: true, sameSite: 'lax', path: '/' });
|
|
29
|
+
revalidatePath('/preferences');
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### `app/preferences/page.tsx`
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { cookies } from 'next/headers';
|
|
37
|
+
import { saveTheme } from './actions';
|
|
38
|
+
|
|
39
|
+
export default async function Preferences() {
|
|
40
|
+
const store = await cookies();
|
|
41
|
+
const theme = store.get('theme')?.value === 'dark' ? 'dark' : 'light';
|
|
42
|
+
return <main>
|
|
43
|
+
<h1>Preferences</h1>
|
|
44
|
+
<p>Current theme: {theme}</p>
|
|
45
|
+
<form action={saveTheme}>
|
|
46
|
+
<select name="theme" defaultValue={theme} aria-label="Theme">
|
|
47
|
+
<option value="light">Light</option>
|
|
48
|
+
<option value="dark">Dark</option>
|
|
49
|
+
</select>
|
|
50
|
+
<button type="submit">Save</button>
|
|
51
|
+
</form>
|
|
52
|
+
</main>;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Server Actions accept untrusted input even when invoked through a form you
|
|
57
|
+
rendered. Check authentication, authorization and input on every protected
|
|
58
|
+
mutation. For real session cookies, use the application's session library and
|
|
59
|
+
production HTTPS policy, including appropriate secure cookie settings.
|
|
60
|
+
|
|
61
|
+
## Fetch deliberately
|
|
62
|
+
|
|
63
|
+
Choose freshness explicitly. Request-specific or sensitive reads normally need
|
|
64
|
+
`fetch(url, { cache: 'no-store' })`. Shared public data can opt into
|
|
65
|
+
`cache: 'force-cache'` and `next: { revalidate: seconds, tags: [...] }`. The
|
|
66
|
+
`next` extension belongs to PRNext's server fetch integration, not browser fetch.
|
|
67
|
+
Check `response.ok` and validate the returned data before using it.
|
|
68
|
+
|
|
69
|
+
Under the default route configuration, an ordinary fetch or `next.tags` alone
|
|
70
|
+
does not request persistent caching. Route configuration can change defaults;
|
|
71
|
+
inspect it before diagnosing a cache. Avoid conflicting `cache` and `revalidate`
|
|
72
|
+
options. A successful fetch cache hit is different from cached HTML, a browser
|
|
73
|
+
router cache hit or a compiler cache hit.
|
|
74
|
+
|
|
75
|
+
`unstable_cache` caches JSON-serializable function results. A runnable public-data
|
|
76
|
+
example:
|
|
77
|
+
|
|
78
|
+
### `lib/catalog.ts`
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { unstable_cache } from 'next/cache';
|
|
82
|
+
|
|
83
|
+
export const readCatalog = unstable_cache(
|
|
84
|
+
async () => [{ id: 'demo', name: 'Demo product' }],
|
|
85
|
+
['public-catalog-v1'],
|
|
86
|
+
{ tags: ['catalog'], revalidate: 60 },
|
|
87
|
+
);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The static array stands in for a real server-side data read. Do not perform
|
|
91
|
+
mutations in the cached callback. Read cookies/headers outside `unstable_cache`
|
|
92
|
+
and pass required values as arguments. Include tenant/user identity in any
|
|
93
|
+
appropriate cache key and authorize before access; never treat a shared cache as
|
|
94
|
+
a session store. Avoid caching private data unless its isolation is deliberate
|
|
95
|
+
and tested. Changes in closed-over values need explicit key parts or arguments.
|
|
96
|
+
|
|
97
|
+
## Invalidate in the mutation
|
|
98
|
+
|
|
99
|
+
`revalidatePath('/preferences')` invalidates a concrete path. A dynamic pattern
|
|
100
|
+
requires its kind, such as `revalidatePath('/products/[slug]', 'page')`.
|
|
101
|
+
`revalidateTag('catalog', 'max')` marks tagged data stale for revalidation;
|
|
102
|
+
`updateTag('catalog')` expires it for read-your-own-writes in a Server Action.
|
|
103
|
+
`updateTag` is action-only; path/tag revalidation also supports Route Handlers.
|
|
104
|
+
Perform the underlying successful write before invalidating its cache.
|
|
105
|
+
|
|
106
|
+
Invalidation APIs are rejected during rendering, inside a cached callback and
|
|
107
|
+
after response headers have been sent. They do not delete unrelated build caches
|
|
108
|
+
or restart the server. Custom cache handlers can delegate these semantics; do
|
|
109
|
+
not infer their hit rate from PRNext's native-cache diagnostics.
|
|
110
|
+
|
|
111
|
+
The installed implementation also has `cacheComponents`, `'use cache'`,
|
|
112
|
+
`cacheLife` and `cacheTag` support. These are additional cache contracts; do not
|
|
113
|
+
enable them to silence a request-context error or assume their complete upstream
|
|
114
|
+
behavior. Keep a working `unstable_cache` or fetch solution unless the project
|
|
115
|
+
needs a different model.
|
|
116
|
+
|
|
117
|
+
## Background work and durable data
|
|
118
|
+
|
|
119
|
+
`after()` from `next/server` is supported in Node Route Handlers and Server
|
|
120
|
+
Actions. It runs tracked callbacks after the response completes or disconnects;
|
|
121
|
+
it is not supported for Server Components or Edge lifecycles. Cookie reads are
|
|
122
|
+
allowed in that retained context, but cookie writes and path/tag invalidation
|
|
123
|
+
are rejected there. Invalidate before returning from the mutation.
|
|
124
|
+
|
|
125
|
+
Tracked callbacks are bounded by the route's `maxDuration` and shutdown
|
|
126
|
+
deadlines; forced termination can interrupt them. Use an external durable queue
|
|
127
|
+
for work that must survive a restart. Module globals, local runtime caches and
|
|
128
|
+
temporary files are not substitutes for a database or durable job store.
|
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
For an existing reverse proxy, bind the application to loopback and configure
|
|
24
|
+
the proxy according to the deployment environment. Set required production
|
|
25
|
+
environment variables and exercise a real health route before switching
|
|
26
|
+
traffic. Check navigation, static assets, actions and cookies over the actual
|
|
27
|
+
public HTTPS origin. Changes to DNS, service managers, public access and
|
|
28
|
+
production traffic need the user's deployment scope; a local build does not
|
|
29
|
+
authorize them.
|
|
30
|
+
|
|
31
|
+
An optional `prnext.config.mjs` with `output: 'standalone'` generates traced
|
|
32
|
+
standalone output under the build directory. Follow the generated artifact's
|
|
33
|
+
entrypoint (`node server.js` from its standalone directory) and preserve its
|
|
34
|
+
relative files. Build for the target OS/architecture and retain compatible Node;
|
|
35
|
+
a standalone bundle is not a universal executable. Read the shipped
|
|
36
|
+
[build output contract](../../build/ADAPTERS.md) for artifact boundaries.
|
|
37
|
+
|
|
38
|
+
## Static browser output
|
|
39
|
+
|
|
40
|
+
PRNext can serve a plain HTML/CSS/JavaScript directory:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
prnext build ./my-site
|
|
44
|
+
prnext start ./my-site --hostname 127.0.0.1 --port 3000
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For output already produced by another builder, run that builder first, then
|
|
48
|
+
select its **public browser directory** explicitly:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
npm run build
|
|
52
|
+
prnext build --adapter static --from dist --spa
|
|
53
|
+
prnext output --json
|
|
54
|
+
prnext start --hostname 127.0.0.1 --port 3000
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use `--spa` only when the browser router needs an `index.html` fallback. Omit it
|
|
58
|
+
for a multipage site. `--adapter auto` can detect completed output; multiple
|
|
59
|
+
candidates require `--from`. Importing output never executes the other builder.
|
|
60
|
+
Vite browser builds, Astro static output, SvelteKit static output and Nuxt
|
|
61
|
+
generated output can fit this model; their SSR servers and server API routes do
|
|
62
|
+
not. Never point `--from` at a source/server directory or anything containing
|
|
63
|
+
credentials. Static browser assets are public.
|
|
64
|
+
|
|
65
|
+
`output: 'export'` in a supported React configuration is another build mode;
|
|
66
|
+
it does not make request-time features such as private sessions or mutations
|
|
67
|
+
available on a static file host. Test all required routes before choosing it.
|
|
68
|
+
|
|
69
|
+
## Your infrastructure or PRNext Host
|
|
70
|
+
|
|
71
|
+
PRNext is MIT-licensed and supports self-hosting. You can manage a production
|
|
72
|
+
process with your existing infrastructure or the explicit `pstart`, `pstatus`,
|
|
73
|
+
`plogs`, `prestart` and `pstop` commands; read `prnext pstart --help` first.
|
|
74
|
+
`prnext host` is the local multi-application gateway command, distinct from the
|
|
75
|
+
managed PRNext Host service. Process replacement does not roll back database
|
|
76
|
+
changes or external effects. Avoid replacing a live service while testing docs.
|
|
77
|
+
|
|
78
|
+
[PRNext Host](https://prnext.dev/host) offers an optional managed path, including
|
|
79
|
+
deployment workflows linked to an AI assistant through MCP. Check current service
|
|
80
|
+
availability and pricing there rather than promising an old rate or automatic
|
|
81
|
+
access. Choose it when the user wants PRNext-managed hosting; self-hosting remains
|
|
82
|
+
available.
|
|
83
|
+
|
|
84
|
+
Where the connected Host deployment API supports this CLI, preview sources
|
|
85
|
+
before any upload:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
prnext deploy --dry-run
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
With deployment authorization and the intended account/server selected, the
|
|
92
|
+
workflow is `prnext login`, `prnext deploy`, then `prnext update` for the linked
|
|
93
|
+
project. Inspect each command's `--help`. CLI availability alone does not prove
|
|
94
|
+
that a given Host server supports every candidate capability. Do not claim an
|
|
95
|
+
upload or queued build is a live site; verify the returned deployment status
|
|
96
|
+
and its actual URL.
|
|
97
|
+
|
|
98
|
+
Cloud archives exclude standard credential/environment and generated paths, but
|
|
99
|
+
review the dry run for project-specific sensitive files. Use remote project
|
|
100
|
+
environment settings for secrets. `NEXT_PUBLIC_` variables and values deliberately
|
|
101
|
+
placed in client code are public. Importing production environment variables is
|
|
102
|
+
an explicit choice, not a reason to print credentials or copy `.env` into assets.
|
|
103
|
+
|
|
104
|
+
## Observe before tuning
|
|
105
|
+
|
|
106
|
+
Use `prnext start --inspect` and `prnext inspect --json` for sampled route/cache
|
|
107
|
+
and runtime observations. `prnext analyze --json` describes built browser
|
|
108
|
+
JavaScript; it is not an SSR latency measurement. A production profile can be
|
|
109
|
+
selected with `--profile balanced|speed|memory|classic`; benchmark the real
|
|
110
|
+
workload before changing defaults. A benchmark from another machine or profile
|
|
111
|
+
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,146 @@
|
|
|
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
|
+
## Minimal App Router application
|
|
23
|
+
|
|
24
|
+
For a new application, start with the manifest below, then install dependencies.
|
|
25
|
+
For an existing application, merge only the necessary scripts and preserve its
|
|
26
|
+
other fields. Follow [Compatibility](compatibility.md) for a Next.js migration.
|
|
27
|
+
|
|
28
|
+
### `package.json`
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"name": "my-prnext-app",
|
|
33
|
+
"private": true,
|
|
34
|
+
"type": "module",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"dev": "prnext dev",
|
|
37
|
+
"build": "prnext build",
|
|
38
|
+
"start": "prnext start",
|
|
39
|
+
"check": "prnext check",
|
|
40
|
+
"typecheck": "prnext typecheck"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Install with the existing manager; for npm:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
npm i --save-exact @thomas.f/prnext react@19.3.1 react-dom@19.3.1 react-server-dom-webpack@19.3.1
|
|
49
|
+
npm i -D typescript @types/react@19 @types/react-dom@19 @types/node
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`--save-exact` pins the resolved framework and React family in the manifest;
|
|
53
|
+
commit the resulting lockfile as well. An unqualified PRNext install follows
|
|
54
|
+
npm's `latest` tag. Use
|
|
55
|
+
`@alpha` or a specific published version only when that is the intended release;
|
|
56
|
+
do not assume a local source candidate exists on npm. If it installs another
|
|
57
|
+
release, read that release's bundled documentation and peer requirements.
|
|
58
|
+
|
|
59
|
+
Create the following TypeScript configuration only if the project has none.
|
|
60
|
+
|
|
61
|
+
### `tsconfig.json`
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"compilerOptions": {
|
|
66
|
+
"target": "ES2022",
|
|
67
|
+
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
|
68
|
+
"module": "ESNext",
|
|
69
|
+
"moduleResolution": "Bundler",
|
|
70
|
+
"jsx": "preserve",
|
|
71
|
+
"strict": true,
|
|
72
|
+
"noEmit": true,
|
|
73
|
+
"skipLibCheck": true
|
|
74
|
+
},
|
|
75
|
+
"include": ["**/*.ts", "**/*.tsx"]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `app/layout.tsx`
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import type { ReactNode } from 'react';
|
|
83
|
+
|
|
84
|
+
export const metadata = {
|
|
85
|
+
title: 'My PRNext app',
|
|
86
|
+
description: 'A React application served with PRNext.',
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
90
|
+
return <html lang="en"><body>{children}</body></html>;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `app/page.tsx`
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
export default function Home() {
|
|
98
|
+
return <main><h1>Hello from PRNext</h1></main>;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Start development:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
npx --no-install prnext check --json
|
|
106
|
+
npm run dev
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use the URL printed by the server. Do not assume port 3000 is free or stop
|
|
110
|
+
unrelated servers to obtain it. An explicit development port is supported:
|
|
111
|
+
`npm run dev -- --port 3001`.
|
|
112
|
+
|
|
113
|
+
No configuration file is required to build the two components. When needed, keep one
|
|
114
|
+
`prnext.config.js|mjs|cjs|ts` or `next.config.js|mjs|cjs|ts`; multiple configuration
|
|
115
|
+
files are rejected. For a new application using generated route declarations,
|
|
116
|
+
`prnext.config.mjs` can contain:
|
|
117
|
+
|
|
118
|
+
### `prnext.config.mjs`
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
export default { typedRoutes: true };
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Validate each layer
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
npx --no-install prnext check --json
|
|
128
|
+
npx --no-install prnext typegen --json
|
|
129
|
+
npm run typecheck
|
|
130
|
+
npm run build
|
|
131
|
+
npm run start -- --hostname 127.0.0.1 --port 3001
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`check` diagnoses configuration, routes, Node, native components and dependencies
|
|
135
|
+
without compiling or installing. Project configuration is evaluated: run it only
|
|
136
|
+
for trusted source. `typegen` and `typecheck` require TypeScript installed in the
|
|
137
|
+
application and an existing tsconfig. They can update the selected tsconfig and
|
|
138
|
+
`prnext-env.d.ts` to connect generated route declarations and missing Next-style
|
|
139
|
+
type aliases, preserving existing/inherited settings. `typecheck` checks semantic
|
|
140
|
+
errors even if `typescript.ignoreBuildErrors` is configured.
|
|
141
|
+
|
|
142
|
+
A successful production build still needs request and browser verification.
|
|
143
|
+
Test navigation, interaction, hydration and the application's important error
|
|
144
|
+
paths. Keep `.prnext/`, `.prnext-types/`, `.prnext-dev/` and `.prnext-cache/` out
|
|
145
|
+
of Git; keep the project's reviewed lockfile in Git. Do not delete generated
|
|
146
|
+
directories while another process is using them.
|
|
@@ -0,0 +1,132 @@
|
|
|
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
|
+
## Dynamic segments
|
|
24
|
+
|
|
25
|
+
`app/products/[slug]/page.tsx` matches `/products/example`. App `params` and
|
|
26
|
+
`searchParams` are asynchronous; await them. This complete page needs no database
|
|
27
|
+
or network request:
|
|
28
|
+
|
|
29
|
+
### `app/products/[slug]/page.tsx`
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
export default async function Product({
|
|
33
|
+
params,
|
|
34
|
+
searchParams,
|
|
35
|
+
}: {
|
|
36
|
+
params: Promise<{ slug: string }>;
|
|
37
|
+
searchParams: Promise<{ ref?: string | string[] }>;
|
|
38
|
+
}) {
|
|
39
|
+
const { slug } = await params;
|
|
40
|
+
const { ref } = await searchParams;
|
|
41
|
+
return <main>
|
|
42
|
+
<h1>{slug}</h1>
|
|
43
|
+
<p>Reference: {Array.isArray(ref) ? ref.join(', ') : ref || 'none'}</p>
|
|
44
|
+
</main>;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`[...slug]` is a required catch-all; `[[...slug]]` is optional. Catch-all values
|
|
49
|
+
are arrays of path segments. Use `generateStaticParams()` only for values that
|
|
50
|
+
can safely be produced at build time. Build-time prerendering can execute page
|
|
51
|
+
code, so avoid mutations and unavailable request-dependent services there.
|
|
52
|
+
|
|
53
|
+
## Isolate client interaction
|
|
54
|
+
|
|
55
|
+
Keep a small client component for state and browser APIs.
|
|
56
|
+
|
|
57
|
+
### `app/counter.tsx`
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
'use client';
|
|
61
|
+
|
|
62
|
+
import { useState } from 'react';
|
|
63
|
+
|
|
64
|
+
export default function Counter() {
|
|
65
|
+
const [count, setCount] = useState(0);
|
|
66
|
+
return <button onClick={() => setCount(value => value + 1)}>
|
|
67
|
+
Count: {count}
|
|
68
|
+
</button>;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Import this component from a server page to render it. Do not turn the entire
|
|
73
|
+
layout into a Client Component to fix one hook error. A client boundary includes
|
|
74
|
+
its imported code: never import database clients, filesystem code or credentials
|
|
75
|
+
through it. Pass appropriate serializable values across the boundary. A Server
|
|
76
|
+
Action is an explicit supported server reference, not an ordinary callback prop.
|
|
77
|
+
|
|
78
|
+
Client Components can participate in server rendering. Read `window`,
|
|
79
|
+
`localStorage` and viewport-dependent state in a browser lifecycle such as
|
|
80
|
+
`useEffect`, not unconditionally during render. Server and first browser render
|
|
81
|
+
must agree. Use `.ts` or `.tsx` for `'use client'` and `'use server'` boundaries;
|
|
82
|
+
PRNext rejects those directives in `.mts`/`.cts` instead of silently misbundling.
|
|
83
|
+
|
|
84
|
+
## Navigation and typed routes
|
|
85
|
+
|
|
86
|
+
Existing application imports such as `next/link`, `next/navigation`,
|
|
87
|
+
`next/headers` and `next/server` are adapted by the PRNext compiler for supported
|
|
88
|
+
APIs. Scoped equivalents use `@thomas.f/prnext/link`, `/navigation`, `/headers`
|
|
89
|
+
and `/server`. Do not globally replace working imports during a migration, and
|
|
90
|
+
do not assume compiler aliases apply to an arbitrary external Node script.
|
|
91
|
+
|
|
92
|
+
Use `Link` for in-app links and App `useRouter` from `next/navigation` inside a
|
|
93
|
+
Client Component. Pages `useRouter` comes from `next/router`; they are different
|
|
94
|
+
contracts. Server code can call `redirect()` or `notFound()` from
|
|
95
|
+
`next/navigation`; let their control-flow exceptions reach the framework.
|
|
96
|
+
|
|
97
|
+
With `typedRoutes: true`, `prnext typegen` writes a discovered route registry.
|
|
98
|
+
For the dynamic page above, this materializes an encoded URL:
|
|
99
|
+
|
|
100
|
+
### `lib/product-url.ts`
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { route } from '@thomas.f/prnext';
|
|
104
|
+
|
|
105
|
+
export const productUrl = route('/products/[slug]', { slug: 'blue mug' });
|
|
106
|
+
// /products/blue%20mug
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Pass catch-all parameters as arrays. The helper rejects missing/unknown
|
|
110
|
+
parameters, separators and dot segments. Add query strings through
|
|
111
|
+
`URLSearchParams`; do not embed query or fragment syntax in the route pattern.
|
|
112
|
+
Generated route checking is PRNext's registry, not the Next.js language-service
|
|
113
|
+
plugin.
|
|
114
|
+
|
|
115
|
+
## Route Handlers
|
|
116
|
+
|
|
117
|
+
An App Route Handler exports HTTP methods and returns a Web `Response` or
|
|
118
|
+
`NextResponse`.
|
|
119
|
+
|
|
120
|
+
### `app/api/health/route.ts`
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
export function GET() {
|
|
124
|
+
return Response.json({ ok: true });
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Read a body with `await request.json()` or `await request.formData()` in a
|
|
129
|
+
handler that accepts `request: Request`. Validate its shape and authorize access
|
|
130
|
+
before writing data. An App Route Handler is not a Pages `(req, res)` API handler.
|
|
131
|
+
The example uses the default Node runtime; do not opt into Edge without checking
|
|
132
|
+
all dependencies and the installed Edge restrictions.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Troubleshooting and live verification
|
|
2
|
+
|
|
3
|
+
[AI documentation index](../../AI.md)
|
|
4
|
+
|
|
5
|
+
## Collect a useful failure
|
|
6
|
+
|
|
7
|
+
Read the installed version, command, working directory, Node version, manager,
|
|
8
|
+
configuration and first complete diagnostic. Separate build errors, semantic
|
|
9
|
+
TypeScript errors, server exceptions, HTTP failures and browser hydration
|
|
10
|
+
errors; they have different causes. Keep secrets, cookies and authorization
|
|
11
|
+
headers out of reports.
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
prnext --version
|
|
15
|
+
prnext check --json
|
|
16
|
+
prnext typecheck --json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`check` does not install, compile or start the application. `typecheck` generates
|
|
20
|
+
types and runs application-installed TypeScript; it needs the application's
|
|
21
|
+
tsconfig and may update generated references. `build` then exercises loaders,
|
|
22
|
+
server/client transforms and prerendering. A browser visit checks the live
|
|
23
|
+
result. Report which layer failed instead of treating one green command as proof
|
|
24
|
+
of all layers.
|
|
25
|
+
|
|
26
|
+
## Common diagnoses
|
|
27
|
+
|
|
28
|
+
| Symptom | Check first |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Native component missing or wrong version | Optional dependencies, supported platform/Node, package lock, framework/native version family and an unintended `PRNEXT_BINARY` override. |
|
|
31
|
+
| Peer or React server/client mismatch | Exact installed React, React DOM and RSC peers; duplicate React instances and a second framework runtime. |
|
|
32
|
+
| Unknown configuration option | The installed version's accepted config; remove or replace only after understanding the intended feature. |
|
|
33
|
+
| Cannot resolve a framework import | Public supported subpath, dependency placement and the migration audit; do not fabricate a private adapter. |
|
|
34
|
+
| Hook or server-only import error | The nearest `'use client'` boundary and everything it imports; keep Node/secret code on the server. |
|
|
35
|
+
| Request API outside context | Move cookie/header access into a request; cached callbacks receive needed values as arguments. |
|
|
36
|
+
| Type errors missing from editor or build | Run `prnext typecheck`; inspect `typescript.tsconfigPath`, inherited roots and existing aliases. |
|
|
37
|
+
| A prerender needs runtime data | Decide whether the route is actually dynamic; do not insert build-time production credentials or suppress the bailout blindly. |
|
|
38
|
+
| Cached content remains stale | The affected cache layer, explicit key/tags and mutation-phase invalidation; custom handlers may delegate caching. |
|
|
39
|
+
|
|
40
|
+
Do not manually patch installed native binaries or force a different release
|
|
41
|
+
into an application. Reinstall through the existing manager and reviewed
|
|
42
|
+
lockfile if installation is the actual problem. Keep the original diagnostic
|
|
43
|
+
when reporting a platform that lacks a compatible published component.
|
|
44
|
+
|
|
45
|
+
## Hydration errors
|
|
46
|
+
|
|
47
|
+
Compare server HTML with the first client render. Typical causes include
|
|
48
|
+
`Date.now()`, random values, locale/time-zone differences, invalid HTML nesting,
|
|
49
|
+
browser-only conditions and client state initialized from storage. Pass stable
|
|
50
|
+
server values as props or move browser reads to a lifecycle. Check that the
|
|
51
|
+
browser loaded assets from the matching build. Use `suppressHydrationWarning`
|
|
52
|
+
only for a deliberately unavoidable, understood mismatch; it is not a general
|
|
53
|
+
repair. Verify the interactive result after the change.
|
|
54
|
+
|
|
55
|
+
## HMR and cache failures
|
|
56
|
+
|
|
57
|
+
Development compiles requested routes and preserves state for compatible edits;
|
|
58
|
+
config/environment, custom Document or incompatible module changes can reload
|
|
59
|
+
the document. Production prerendering and compression are not development HMR.
|
|
60
|
+
An unused route need not rebuild until requested.
|
|
61
|
+
|
|
62
|
+
For a controlled diagnosis, stop only the development process you own and try:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
prnext dev --safe
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Safe mode uses full builds and fresh workers. `PRNEXT_BUILD_CACHE=0` disables
|
|
69
|
+
PRNext's compiler/build caches when set in the current process environment; use
|
|
70
|
+
the syntax appropriate to the user's shell and restore the previous setting
|
|
71
|
+
after the comparison. Optional cache-storage failures should fall back to work,
|
|
72
|
+
while genuine loader errors remain build failures. Do not delete every cache or
|
|
73
|
+
lockfile as a first response, especially with another server running.
|
|
74
|
+
|
|
75
|
+
For production observations:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
prnext start --inspect
|
|
79
|
+
prnext inspect --json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The inspector needs actual traffic for observed timings. Header-ready timings
|
|
83
|
+
exclude the full streaming body, and missing/dropped samples are not zero.
|
|
84
|
+
`prnext routes` describes compiled routes. Bundle size questions use
|
|
85
|
+
`prnext analyze`, after building, rather than interpreting request time as
|
|
86
|
+
compiler performance.
|
|
87
|
+
|
|
88
|
+
## Connect the existing development MCP
|
|
89
|
+
|
|
90
|
+
Start `prnext dev` in the application, then configure a compatible assistant to
|
|
91
|
+
launch the following **stdio MCP command** with its absolute project directory:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
prnext mcp /absolute/path/to/application
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Use the locally installed executable, not an unreviewed remote package. This
|
|
98
|
+
stdio process is a tool server for an MCP client, not a second application
|
|
99
|
+
server. The development endpoint binds to loopback; its private
|
|
100
|
+
`.prnext-dev/tools.json` contains a capability, so never publish or paste that
|
|
101
|
+
file. No new shell-access tool or public debug endpoint is needed.
|
|
102
|
+
|
|
103
|
+
The existing tools include `dev_snapshot`, `dev_logs`, `dev_routes`,
|
|
104
|
+
`dev_route_ensure`, `dev_cache_invalidate`, `dev_source`, `dev_ai_context` and
|
|
105
|
+
`dev_verify`. Read their returned schemas rather than inventing tool arguments.
|
|
106
|
+
|
|
107
|
+
For a fix, capture `dev_snapshot` before editing and retain its `sequence`.
|
|
108
|
+
After the edit, call `dev_verify` with that value as `sinceSequence` and the
|
|
109
|
+
pathname being checked. Keep an actual application browser open. Verification
|
|
110
|
+
requires a newer successful generation and browser evidence that it applied
|
|
111
|
+
that exact build. A missing build or browser is inconclusive; compilation,
|
|
112
|
+
TypeScript or reported browser errors fail the observation. Continue relevant
|
|
113
|
+
application tests: this development observation does not establish complete
|
|
114
|
+
functional correctness.
|
|
115
|
+
|
|
116
|
+
Local MCP works independently of managed hosting. `prnext dev --host-ai` is an
|
|
117
|
+
explicit relay option for a logged-in terminal and a compatible connected Host
|
|
118
|
+
server; it can share requested diagnostics and queued context. Do not enable
|
|
119
|
+
remote sharing or change a user's assistant configuration as a hidden side
|
|
120
|
+
effect of fixing an application.
|
package/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { build } from './build/index.mjs';
|
|
2
|
+
export {createBuilder} from './build/production-builder.mjs';
|
|
3
|
+
export {route} from './runtime/typed-route.mjs';
|
|
2
4
|
export { buildStatic } from './build/static-adapter.mjs';
|
|
3
5
|
export { readBuildOutput, validateBuildOutput } from './build/output-contract.mjs';
|