Documentation
Differences from Next.js
The compatibility boundaries to understand before adopting vinext.
vinext targets the stable Next.js 16 API surface, not undocumented Vercel behavior or every experimental feature. Run
vinext checkagainst your own application before adopting it.
Toolchain
Development, bundling, and production builds run on Vite 8 instead of the Next.js compiler toolchain. Vite plugins can extend the build, while webpack plugins and framework-specific build internals do not carry over automatically.
Deployment
Cloudflare Workers is the primary native target. Standalone Node output and Nitro adapters cover other hosts. Next.js route config values such as runtime and preferredRegion don't choose where code runs, because runtime placement belongs to the selected deployment adapter. Outside cacheComponents, runtime = "edge" still opts an App Router page out of ISR, as it does in Next.js.
Caching
These differences apply to builds without cacheComponents, which follow their own caching rules.
At request time, vinext decides whether a render is dynamic while it renders. (The opt-in prerender and a staged deploy's cacheability probe render the HTML, so they do detect these reads, and the probe's manifest keeps Workers Cache from storing most such paths.) A client navigation requests only the RSC payload, whose render doesn't run client components, so it can't see a "use client" page reading its searchParams, or a useSearchParams() call with no <Suspense> boundary above it. On an otherwise static route, vinext can then store that RSC payload, while Next.js treats the route as dynamic, or fails its build, and stores nothing. Under dynamic = "force-static", both read empty values and the route is static in both, so this doesn't apply. The payload doesn't contain the query, but server-rendered data on the route can stay stale during client navigations until it's revalidated. To match Next.js:
- export
dynamic = "force-dynamic"from the route'slayout.tsx(a"use client"page can't export segment config), or readsearchParamsin a server component page and pass the values down; - wrap
useSearchParams()in<Suspense>, as Next.js requires.
Next.js also treats an otherwise static route as SSG when a layout above its last dynamic segment returns every param from generateStaticParams. vinext doesn't run the generator to classify requests, so it renders such a route on every request unless it exports dynamic = "force-static" or "error". Adding generateStaticParams to the last dynamic segment, even one that returns [], makes the route static in both.
Compatibility
App Router, Pages Router, RSC, Server Actions, middleware, Route Handlers, static generation, ISR, and the commonly used next/* modules are implemented. Cache Components and Partial Prerendering remain incomplete, and build-time image and font optimization do not yet reproduce the full Next.js pipeline.
How to read the docs
If a feature is not listed as a vinext difference, start with the corresponding Next.js documentation. For adoption decisions, the compatibility dashboard is the live view of test coverage, and the issue tracker records known gaps and focused reproductions.