The adapter and the compiled build
How knext's default (standalone) build uses the official Next.js adapter, and how the selectable vinext build relates to it — and which claims each carries.
Scope, stated plainly. knext's default build (build: 'turbopack') uses this adapter: the
adapter hooks described below run on next build, producing the standalone output the official-suite
results on the compatibility matrix were measured on. The selectable build: 'vinext' target — which
compiles your app with vinext, an open-source, Vite-based implementation of
the Next.js framework, into a single executable — does not use this
adapter; the hooks below are never called on that path. Which claim covers which path is tracked
row-by-row on the compatibility matrix.
knext's adapter implements the official Next.js Deployment Adapter API — a small object of the
official NextAdapter shape, shipped as a package export so any app (and the official
compatibility harness) can point at it.
The adapter object
The knext adapter lives in @getknext/core and is exported at @getknext/core/adapter. Its default
export is a NextAdapter:
const adapter: NextAdapter = {
name: 'knext-adapter',
modifyConfig(config, { phase }) {
// defaults output to 'standalone' on phase-production-build
},
async onBuildComplete(ctx) {
// logs output counts + uploads static artifacts to object storage (keyed by buildId)
},
};
export default adapter;modifyConfigdefaultsoutputto'standalone'during the production build. An explicitoutput: 'export'is left untouched, so Next.js runs its own static-export validation, and the knext CLI then refuses the build (on both the Next.js and vinext build targets; the Next.js check honours a customdistDir; both readnext.configliterally, so a value computed at runtime is not detected, and on vinext anoutput: 'export'that sits under a condition or inside a nested value only prints a warning): a static export is not a server deployment, and knext deploys a Next.js server. Removeoutput: 'export', or host theout/folder on a static host.onBuildCompleteuploads the build's static artifacts to the configured object store, keyed bybuildId.
Wiring it into an app
On Next.js 16.2 and later, adapterPath is top-level configuration:
export default {
adapterPath: '@getknext/core/adapter',
};Version note. On Next.js 16.0.x–16.1.x the option lives under experimental instead
(experimental: { adapterPath: '@getknext/core/adapter' }). The 16.2+ config loader auto-migrates
the old experimental key (with a warning), but 16.0.x does not recognize the top-level form
— match the form to your Next.js version.
You can also point adapterPath at a thin local re-export file if you want the adapter contract
visible at the app boundary:
import adapter from '@getknext/core/adapter';
export default adapter;This is the same pattern that knext create scaffolds and the example apps in the knext repo use.
Known issue: dynamic routes and adapterPath
With adapterPath set, a route with dynamicParams = false that receives a parameter not listed in
generateStaticParams answers with a 404 straight away. It does not fall through to a less specific
route (for example a catch-all that would have matched). On Next.js releases before 16.4.0
(16.3.x included) the same request can also fail with a 500 instead of a 404 when a burst of
concurrent prefetches arrives. Both come from the adapter being configured on a server that has no
adapter router in front of it, which is how the standalone server runs.
knext works around it for you, on every Next.js version. knext build, knext deploy and
knext preview clear adapterPath from the standalone server's runtime configuration. The adapter
only does its work during next build, so nothing at runtime depends on it. Unlisted parameters then
fall through to the less specific route exactly as they do on a standalone server without an adapter,
and a request that matches nothing returns a plain 404. Each such request writes an
Error: Internal: NoFallbackError line to the server log.
If you assemble the standalone output without the knext CLI, remove adapterPath from the runtime
configuration in the standalone output yourself.
Tested against the official suite
knext tests the adapter against the official Next.js compatibility suite: the vercel/next.js
deploy-mode e2e harness runs through knext's lifecycle scripts, on a schedule (three runs a day per
cell), on all four default
runtime x builder combinations. The 14-run compatibility credential for those combinations is
in progress, not complete — the compatibility matrix states each cell's
current status. A fast smoke gate additionally runs a Node + Bun
matrix on every change.
The exact scope of that claim — including the four documented architectural exclusions (edge runtime, edge middleware, PPR, cache components) and per-cell status — is on the compatibility credential. Row-by-row feature status lives in the compatibility matrix.
GitLab CI/CD
Deploy from GitLab CI/CD with a kubeconfig — no cloud credentials, no provisioning.
How your app is built
knext's default build compiles your Next.js app with next build into a standalone server, run as a Bun bytecode executable — the official-adapter-verified target. vinext (a single executable) stays selectable.