ADR: client-web deploy convergence (next-on-pages vs OpenNext)
Status: Accepted (2026-04)
Context: Web app standardization plan Phase 4 · Prego Web App Standard §7
Decision
- Long-term target: Align client-web with the same OpenNext → Cloudflare Worker posture as admin-web when a dedicated migration project runs (Phase 4 execution).
- Current posture (unchanged): client-web remains on
@cloudflare/next-on-pagesandpages:builduntil that migration. Next.js is aligned to 16.0.11 with client-web and admin-web; peer warnings fromnext-on-pages(declared range<=15.5.2) are known and tracked alongside Phase 4. - admin-web: Stays on OpenNext (
@opennextjs/cloudflare); Next 16.0.11 withnext.config.mjs(Next 16 + OpenNext dev init incompatible with compilednext.config.tsin this repo).
Middleware vs proxy (Next 16)
Next.js 16 may log that the middleware file convention is deprecated in favor of proxy. Do not switch PREGO Cloudflare apps to proxy.ts yet:
- client-web:
middleware.ts+runtime = 'experimental-edge'— required for@cloudflare/next-on-pages(Edge/_middleware). - admin-web (OpenNext):
opennextjs-cloudflare buildfails with “Node.js middleware is not currently supported. Consider switching to Edge Middleware.” A trialproxy.ts(Node-default) breakscf:build; keepmiddleware.tsuntil OpenNext supports the new convention or documents Edgeproxy.
Revisit when @opennextjs/cloudflare and Next 16 align on proxy + Workers.
Preconditions before migrating client-web to OpenNext
- Staging E2E and
pages:build/ Workercf:buildparity checks for the same routes. - Documented deltas: middleware vs proxy (Next 16 deprecation notice), PWA / next-pwa, edge routes, R2 / presigned flows, and incremental cache behavior — expanded in Phase 4 migration delta checklist below.
- Optional: upgrade or replace
@cloudflare/next-on-pageswhen upstream supports Next 16 officially, or adopt OpenNext-only path for client-web.
Phase 4 migration delta checklist
Use this list when scoping or reviewing a client-web OpenNext migration (compare with current next-on-pages + pages:build). Items are verification targets, not prescriptive implementation steps.
| Area | Current (client-web) | Re-validate on OpenNext / Worker |
|---|---|---|
| Middleware | middleware.ts, runtime = 'experimental-edge' — required for @cloudflare/next-on-pages. | Session redirects, locale cookies, tenant/public routes — parity with Playwright (e2e/**/*.spec.ts) and manual smoke. See Middleware vs proxy. |
| E2E | Root pnpm run test:e2e:client-web (after pnpm run verify:client-web in CI). Default workers: 1; optional PW_WORKERS. | Same suite green against a staging Worker build; add cases if middleware or routing shape changes. |
| PWA | next-pwa in next.config.mjs; public/sw.js emitted on production next build only (gitignored — apps/client-web/AGENTS.md). | Service worker registration, runtimeCaching rules, and manifest.json / precache exclusions — no regressions on Worker host. |
| Route Handlers (BFF) | Zuplo-forwarding routes use export const runtime = 'edge' so pages:build bundles them (apps/client-web/AGENTS.md). | Confirm OpenNext output includes each app/api/**/route.ts; adjust runtime if the adapter documents Node vs Edge for the target. |
| Typecheck / strip | prego-strip-next-dev-types-from-tsconfig before tsc / build (@platform/next-dev-scripts). | Same strip in package.json scripts; pnpm run typecheck and cf:build (or equivalent) pass. |
| Build | pnpm run pages:build (@cloudflare/next-on-pages). | pnpm run cf:build (or project OpenNext command) — compare function count, cold paths, and any static vs dynamic route differences. |
| Caching / R2 | Pages — incremental cache semantics differ from admin-web OpenNext R2 cache bucket. | Document ISR / fetch cache / static behavior for the migrated app; align with prego-pulumi / wrangler bindings if R2 is introduced for client-web. |
Links
- Web app refactor continuation plan — Phase E / roadmap table.