* fix(pages-router): set x-nextjs-deployment-id on SSG _next/data responses
Pages Router `/_next/data/<buildId>/<page>.json` responses were missing the
`x-nextjs-deployment-id` response header that Next.js sets on these routes
when a deployment ID is configured. The client router reads this header to
detect when a new deployment has been rolled out and triggers a hard
navigation for deployment-skew protection.
Root cause: the `isDataReq` short-circuit path in `pages-page-handler.ts`
that builds the JSON envelope (`buildNextDataJsonResponse`) never injected
the header. Next.js's `pages-handler.ts` sets `NEXT_NAV_DEPLOYMENT_ID_HEADER`
on every `isNextDataRequest` response (success, redirect, and notFound cases).
Fix: read `process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID`
(the runtime-available deployment ID, inlined at build time by Vite's define
transform) and set `x-nextjs-deployment-id` on the `_next/data` response
headers when a deployment ID is configured.
Maps to test: `pages ssg data deployment skew - hard navigate when a new
deployment occurs > header with deployment id > header is set on data routes`.
Fixes#1829
* fix(pages-router): complete x-nextjs-deployment-id parity for _next/data (bonk #1829)
Address all three ask-bonk findings on PR #1863:
1. Incomplete parity — add x-nextjs-deployment-id to redirect and notFound _next/data
exits in pages-page-data.ts (buildPagesRedirectResponse, buildPagesDataNotFoundResponse).
Thread deploymentId through ResolvePagesPageDataOptions and pass it from
pages-page-handler.ts, matching the success-path pattern already in that file.
2. Dev/prod parity — patch dev-server.ts to set x-nextjs-deployment-id on all three
_next/data exits: the writeGsspRedirect isDataReq path, the getStaticPaths/
getServerSideProps/getStaticProps notFound isDataReq paths, and the success
JSON envelope short-circuit (isDataReq block). Mirrors the prod handler.
3. Add regression tests asserting x-nextjs-deployment-id is present on _next/data
success / redirect / notFound responses in both pages-page-data.test.ts (unit,
via deploymentId option) and pages-page-handler.test.ts (integration, via
process.env.__VINEXT_DEPLOYMENT_ID), and absent when no env var is set.
* fix(pages-router): add x-nextjs-deployment-id to wrong-buildId/route-miss _next/data 404s (#1829)
Fixes the deployment-skew gap identified in review: `buildNextDataNotFoundResponse` now
includes the `x-nextjs-deployment-id` header so all three wrong-buildId/route-miss exits
(normalizePagesDataRequest, prod-server Node path, pages-page-handler route-miss) surface
the deployment ID to the client router. Adds unit tests for the new header on all relevant
exits.
* fix(pages-router): set deployment-id header on remaining two dev-mode _next/data 404 exits (#1829)
Patches the stale-buildId 404 in the vite-dev middleware (index.ts) and
the route-miss data 404 in createSSRHandler (dev-server.ts) to set
x-nextjs-deployment-id, matching prod parity via buildNextDataNotFoundResponse().
* test(pages-router): cover dev-mode _next/data deployment-id header exits
Drive the two dev-only exits flagged in review through the real fixture
dev server: the wrong-buildId data 404 in the plugin middleware
(index.ts) and createSSRHandler's route-miss data 404 (dev-server.ts),
plus the dev success path and the no-deployment-id case.
* fix(pages-router): skip deployment-id header on /_error and /500 data success responses
Next.js pages-handler.ts guards the success-path x-nextjs-deployment-id
injection with `!isErrorPage && !is500Page`. Mirror that exclusion in
both the prod success short-circuit (pages-page-handler.ts) and the dev
one (dev-server.ts), and lock it in with a prod unit test (/_error and
/500) plus a dev integration test (/500).
* feat(pages-router): implement _next/data JSON endpoint
Recognize `/_next/data/<buildId>/<page>.json` in dev and prod request
pipelines. The URL is normalized to the page path BEFORE middleware
runs (matching Next.js' `handleNextDataRequest`), and the server emits
`{ pageProps }` as JSON with `Content-Type: application/json` instead
of the rendered HTML.
Closes#1330
* fix(pages-router): address bigbonk findings on _next/data endpoint
- Delegate JSON envelope construction from the generated entry to the
typed `buildNextDataJsonResponse` helper so the envelope shape lives
in one place (entries stay thin per AGENTS.md).
- Return a JSON 404 from `resolvePagesPageData` when `getStaticPaths`
with `fallback: false` rejects the path for a data request. Without
this, client-side navigations to unlisted slugs got an HTML 404 body
which fails to parse as JSON in the Next.js client router.
- Apply the same JSON-404 gating in the dev server for
`getStaticPaths fallback:false`, `getServerSideProps.notFound`, and
`getStaticProps.notFound` paths.
- Read the dev buildId from the plugin's resolved `nextConfig.buildId`
first so a user-supplied `generateBuildId` is honored, matching the
value embedded into the prod server entry.
- Add coverage for `getStaticProps` data requests and the
`fallback:false` JSON-404 path.
* chore: drop unused NextDataMatch export (knip)
* fix(pages-router): JSON 404 for dev stale buildId; HTML 404 for gSSP/gSP notFound on HTML nav
Follow-ups from bigbonk round 2:
- Dev request pipeline now returns a JSON 404 when `_next/data/<wrong>` is
hit, mirroring the prod-server path. Previously the dev fall-through
served Vite's HTML 404, breaking client routers that try to parse the
body as JSON.
- `resolvePagesPageData` now gates the gSSP/gSP `notFound: true` 404 body
on `isDataReq` so HTML navigations get the HTML 404 page and data
requests get the JSON envelope. Previously both shapes always returned
the JSON body, which surfaced text-content-type mismatches on HTML
navigations through gSSP/gSP `notFound`.