1# packages/frontend-frameworks/fixtures/nextjs
2
3E2e fixture for `@alchemy.run/frontend-frameworks/nextjs` — the wrangler-free Next.js
4(OpenNext-based) framework integration.
5
6The app exercises the OpenNext long tail:
7
8- an SSR app-router page (`/`, `force-dynamic`)
9- an API route (`/api/hello`)
10- an API route reading a `Text` binding via `getCloudflareContext()`
11 (`/api/binding`)
12- an ISR page (`/isr`) — asserts the prerendered payload serves from the
13 read-only static-assets incremental cache (revalidation writes are a known
14 dev-v1 gap; a writable local cache backend is a later phase)
15- an edge middleware rewrite (`/mw-rewrite` → `/api/hello`) plus a response
16 header on `/api/*`
17- static assets (`public/static.txt` and `_next/static/*` client chunks)
18- a client-interactive page (`/counter`) proving hydration
19
20## Commands
21
22```sh
23bun run build # e2e build — OpenNext pipeline + final bundle pass -> dist/build.json
24bun run preview # e2e preview — miniflare over dist/build.json
25bun run dev # e2e dev --port 3104 — built worker under cloudflare-runtime (workerd)
26bun run test # build + playwright (live = miniflare, dev = cloudflare-runtime)
27```
28
29## Notes
30
31- `wrangler` resolves to the inert stub in
32 `packages/frontend-frameworks/src/nextjs/wrangler-stub` — only its `package.json` version field is
33 ever read (OpenNext's `ensureNextjsVersionSupported`); no wrangler code is
34 installed or executed.
35- The OpenNext pipeline runs `npx next build` internally (the fixture's own
36 `build` script is `e2e build`, which would recurse).
37- Dev (default `"preview"` mode) is production parity: the built worker
38 served by workerd with `ASSETS` (run-worker-first), `WORKER_SELF_REFERENCE`
39 (self service binding), and the same-script SQLite `DOQueueHandler` durable
40 object. No HMR.
41- `test/hmr.test.ts` exercises dev v2 (`dev: { mode: "hmr" }`): the real
42 `next dev` (Turbopack HMR) in Node with the `TEST_TEXT` binding proxied
43 from cloudflare-runtime onto OpenNext's `getCloudflareContext()` contract —
44 no `initOpenNextCloudflareForDev()`, no wrangler. The spec builds its own
45 `Framework` layer (the harness `dev` fixture stays wired to preview mode);
46 `scripts/hmr-repro.mjs` is a minimal manual runner for the same path. App
47 code runs in Node in this mode — CF-specific behavior and ISR/caching
48 semantics still need preview (see `packages/nextjs/README.md`).