Re-exports sign-up, sign-in-sso, sign-in-partner, sign-in-mfa,
forgot-password(-mfa), reset-password, cli/login, and the Stripe
partners login page under `routes/_auth/`. Each wrapper replicates the
page's `getLayout` treatment; pages that inline their own layout are
rendered directly. `withAuth`-wrapped default exports stay intact.
Also hardens `compat/next/link.tsx` to accept Next's `UrlObject`
(`{pathname, query, hash}`) href form — sign-in.tsx uses this to forward
`router.query` into SSO/sign-up links, and the old shim was coercing it
to "[object Object]". Anchor attrs and `replace` now spread through;
remaining Next-only props are dropped silently.
Two App Router routes (incident-banner, incident-status) and a few
type-only uses elsewhere import from 'next/server'. The Vite
nextCompat guard was 500ing on the build. Shim exposes
NextResponse.json (the only value surface used) and a type alias
NextRequest = Request.
Adds `compat/next/api.ts` exposing `toWebHandler(nextHandler)`: an
adapter that builds a NextApiRequest-shaped object from a Web
`Request` (lowercased headers, parsed cookies, merged query + route
params, JSON/urlencoded body parsing) and a NextApiResponse proxy
capturing `status` / `setHeader` / `json` / `send` / `write` / `end`
/ `redirect`. Handler output is buffered then returned as a Web
`Response`. Handlers that already return a `Response` (edge-runtime
style) pass through unchanged.
Each ported route in `routes/api/**` is a 9-line re-export: import
the default export from `pages/api/...`, wrap with `toWebHandler`,
register under `server.handlers.{GET,POST,...}`. `apiWrapper` and
`apiAuthenticate` stay untouched — they run inside the shim seeing
the shaped `req`/`res`.
Coverage: 88 of the 90 `pages/api/**` handlers. The two exceptions
need bespoke rewrites and are tracked in TANSTACK_MIGRATION.md:
- `v1/projects/[ref]/functions/[slug]/body.ts` — pipes
`fs.createReadStream` into `res`; needs a Web-stream rewrite.
- `mcp/index.ts` — the MCP SDK transport expects Node req/res; need
to check for a Web-fetch transport option.
Also adds `query` (params + search) to the existing `next/router`
shim to unblock components like FeedbackDropdown that read
`router.query.ref`.
First two pages ported under the minimum-diff Path A strategy: the
TanStack route wraps the page default-exported from pages/ rather
than rewriting the body. Layout chains provided by pathless _app /
_auth pathless routes + sibling-file layouts, reading per-leaf props
(AccountLayout title, DefaultLayout headerTitle) from route
staticData via useMatches.
Supporting fixes:
- compat/next/router: add `query` (params + search) so components
like FeedbackDropdown that read `router.query.ref` keep working
under the shim.
- ConnectSheet content loader: switch to `import.meta.glob` for
Vite (the template path spans multiple directories so
dynamic-import-vars can't analyse it), guarded with
`import.meta.env.SSR` to keep the 37 content modules out of the
SSR graph — they reshuffle chunks enough to surface circular-dep
bugs in unrelated modules. Next/webpack falls through a try/catch
to the existing `import(\`./content/\${filePath}/content\`)`.
TANSTACK_MIGRATION.md tracks per-page status during the migration.
Extends next/router shims to expose router.pathname as the route
pattern (Next pages-router semantics) rather than the resolved URL,
by converting TanStack's matched route id ($param → [param]). Also
adds push/replace/asPath to the next/router shim so consumers like
RouteValidationWrapper can keep working unchanged.
Also adds next/legacy/image and useSearchParams shims that the build
uncovered, and bumps @radix-ui/react-visually-hidden to ^1.2.3 so
react-select's import of VISUALLY_HIDDEN_STYLES resolves at runtime.
- Wrap Outlet with StudioCommandProvider (imported as CommandProvider,
matching pages/_app.tsx) inside AiAssistantStateContextProvider so
the command menu context works in the Vite build.
- Add an events adapter to both next/router and next/compat/router
shims so workspace code that does router.events.on('routeChangeX')
(CommandProvider, telemetry, usePreventNavigationOnUnsavedChanges,
QueryInsightsTable, ...) doesn't crash on `.on` of undefined.
Subscriptions proxy to TanStack Router's router.subscribe
(routeChangeStart -> onBeforeLoad, routeChangeComplete -> onResolved)
and .off unsubscribes by handler identity. The proxy is cached per
router instance via a WeakMap so effect deps stay stable.
- Wrap Outlet with DevToolbarProvider from 'dev-tools' inside the
ThemeProvider, and render <DevToolbar extraTabs={...} /> +
<DevToolbarTrigger /> as siblings, mirroring pages/_app.tsx.
- Guard everything behind IS_DEV_TOOLBAR_ENABLED (NEXT_PUBLIC_ENVIRONMENT
in {local, staging}) so prod bundles tree-shake the dev-only code.
- Use React.lazy + Suspense directly for ResourceWarningsTab since
__root.tsx is new code we control — the compat shim is only for
existing workspace code that still imports next/dynamic.
- Add the next/dynamic -> compat/next/dynamic.tsx entry to nextShims
so any workspace file pulled transitively (e.g. common, ui-patterns)
keeps working via the compat layer. Shim proxies to React.lazy +
Suspense and honours the ssr: false option.
- Wire ErrorBoundary + Sentry-aware handler into routes/__root.tsx to
mirror pages/_app.tsx; switch the handler's Sentry import to
framework-agnostic @sentry/react.
- Add apps/studio/compat/next/ shims (link, router, head, navigation,
image, script, compat/router) that proxy to TanStack Router
equivalents. Shims implement only the surface used today; expand as
new usage appears.
- Combine shim aliasing and a build-time guard into a single Vite
plugin (nextCompat): resolves shimmed next/* ids to local files, and
fails the build on any unshimmed next/* import from workspace source
so we catch regressions during the migration.
- ssr.noExternal lodash to fix CJS named-export interop during
prerender.