cloudflare / cloudflare/vinext
Pages Router: `window.next.router` global not exposed during hydration
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 120
Description
> *This issue was created by an agent analysing CI failures from the [Next.js Deploy Suite](https://github.com/cloudflare/vinext/actions/runs/26163751905) (vinext `main` vs Next.js `v16.2.6`, 2026-05-20).*
## Problem
vinext does not expose `window.next = { router }` during Pages Router client-side hydration. In Next.js, `packages/next/src/client/index.tsx` sets this global during hydration, and it is the only programmatic way to trigger imperative client-side navigation outside React components.
Every test that calls `browser.eval('next.router.push(...)')` or reads `browser.eval('next.router.pathname')` fails immediately with:
```
TypeError: Cannot read properties of undefined (reading 'router')
```
or:
```
ReferenceError: next is not defined
```
Because the navigation never fires, downstream assertions (waiting for page content, checking URLs, verifying router events, checking `window.__SAME_PAGE`) all time out.
## Estimated Impact
~80 test failures across the deploy suite.
## Affected Test Suites
- `test/e2e/middleware-general/test/node-runtime.test.ts` (34 failures)
- `test/e2e/middleware-general/test/index.test.ts` (32 failures)
- `test/e2e/middleware-rewrites/test/index.test.ts` (21 failures)
- `test/e2e/trailing-slashes/with-trailing-slash.test.ts` (20 failures)
- `test/e2e/trailing-slashes/without-trailing-slash.test.ts` (20 failures)
- `test/e2e/basepath/query-hash.test.ts` (10 failures)
- `test/e2e/basepath/router-events.test.ts` (4 failures)
- `test/e2e/use-router-with-rewrites/use-router-with-rewrites.test.ts` (7 failures)
- `test/e2e/with-router/index.test.ts` (3 failures)
- `test/e2e/ignore-invalid-popstateevent/*.test.ts` (5 failures)
## Recommendation
1. **Reproduce first in vinext's own test suite.** Before submitting a PR, add a test case in the relevant `tests/*.test.ts` file that verifies `window.next.router` is exposed on Pages Router pages after hydration. Confirm it fails, then implement the fix.
2. **Study the Next.js implementation.** Look at `packages/next/src/client/index.tsx` in the Next.js source to understand what properties are set on `window.next` and when. At minimum, `window.next.router` must expose `.pathname`, `.query`, `.push()`, `.replace()`, `.events`, and other standard router properties.
3. **Wire up the global in the Pages Router client entry.** The vinext Pages Router client entry (or hydration code) needs to set `window.next = { version, router }` after the router is initialized, mirroring what Next.js does.
4. **Verify dev/prod parity.** Ensure the global is available in both development and production builds.
Contributor guide
Research direction
Start by reproducing the failure in a relevant tests/*.test.ts file, such as test/e2e/with-router/index.test.ts, and add a hydration check for window.next.router. Read packages/next/src/client/index.tsx to compare the expected global and inspect the vinext Pages Router client entry. Done means the router properties and navigation methods are available after hydration in both development and production builds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- next.js, typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100