Getting started
Take a Next.js app from next build to a scale-to-zero Knative service.
Take an existing Next.js app from next build to a scale-to-zero Knative service. knext uses the
vinext, an open-source Vite-based implementation of Next.js, compiled into a single fast executable. (The official Deployment Adapter API remains supported as the suite-verified legacy lane.)
Prerequisites. A Kubernetes cluster with Knative Serving installed (don't have one?
Your first cluster gets you a laptop cluster in minutes), Next.js 16.x, and a
container registry. An object-storage bucket (gcs, s3, minio, or azure) is optional —
start without one (your app serves its static files from its own image, like next start) and add
it later for CDN offload. See
Starting without object storage.
0 · Install the packages
knext ships on the public npm registry under the @getknext scope. No registry
configuration, no auth token — a plain npm i is all it takes.
npm i @getknext/core # the adapter, the config type, and the CLI (bin: kn-next)
npx kn-next --version # the CLI is on your PATH via node_modules/.binTwo optional packages complete the picture — add them only if you need them:
npm i @getknext/db # typed drizzle-orm data layer over your DATABASE_URL
npm i @getknext/lib # runtime helpers: pooled DB clients, health checks, logger| Package | What it is for | Canonical imports |
|---|---|---|
@getknext/core | The official Next.js adapter, the typed deploy config, the ISR cache handler, and the kn-next CLI. Required. | '@getknext/core' (KnativeNextConfig), '@getknext/core/adapter', '@getknext/core/validate' |
@getknext/lib | Runtime helpers for an app running on knext: pooled Postgres clients, a MinIO client, a Cerbos client, health checks, and a preconfigured logger. | '@getknext/lib/clients', '@getknext/lib/health', '@getknext/lib/logger', '@getknext/lib/context' |
@getknext/db | The Data SDK — a thin drizzle-orm layer over your DATABASE_URL, with schema builders and one-shot writer-only migrations. | '@getknext/db', '@getknext/db/schema', '@getknext/db/migrate' |
What each package exports. @getknext/core exports the KnativeNextConfig type from its root,
the adapter from /adapter (what adapterPath points at), the ISR cache handler from
/adapters/cache-handler, and the pure config validator (validateConfig,
ConfigValidationError) from /validate. @getknext/lib exports getDbPool() / getDbPoolRO()
/ closeDbPool(), getMinioClient(), getCerbosClient(), checkDeepHealth() /
checkShallowHealth(), the logger, and the request-correlation helpers — all also re-exported
from the package root. @getknext/db exports getDb() / getDbRO() plus the whole of
drizzle-orm.
1 · Point Next.js at the adapter
Reference the knext adapter from your next.config.ts. The adapter forces output: 'standalone' at
build time.
import type { NextConfig } from 'next';
const config: NextConfig = {
// knext ships the official NextAdapter as a package export.
// adapterPath is top-level config on Next.js 16.2+.
adapterPath: '@getknext/core/adapter',
};
export default config;Next.js 16.0.x–16.1.x: the option lives under experimental on those versions
(experimental: { adapterPath: '@getknext/core/adapter' }). Next.js 16.2+ auto-migrates the old
experimental key with a warning; 16.0.x does not recognize the top-level form.
2 · Write the deploy config
knext reads a typed kn-next.config.ts. The config type is KnativeNextConfig, exported from
@getknext/core. The minimum valid config requires just name and registry. The storage
block is optional: without it, static assets are served from your app's container image — every
deploy says so explicitly — and you can add the block later for bucket/CDN delivery.
import type { KnativeNextConfig } from '@getknext/core';
const config: KnativeNextConfig = {
name: 'acme',
registry: 'registry.example.com/acme',
// Optional — omit to serve static assets from the image (like `next start`):
storage: {
provider: 'gcs', // one of: gcs | s3 | minio | azure
bucket: 'acme-assets',
publicUrl: 'https://storage.googleapis.com/acme-assets',
},
scaling: { minScale: 0, maxScale: 20 }, // minScale 0 = scale to zero
// The default build compiles your app into a single executable (bundled,
// minified, bytecode-precompiled, Bun baked in). See /docs/bun-runtime.
};
export default config;If you configure storage, its provider is validated against gcs | s3 | minio | azure. Each
shells out to that cloud's CLI (gsutil / aws / mc / az), which must be installed and
authenticated in your build environment. See Multi-cloud deploy.
The scaling block also carries the full set of autoscaling knobs (containerConcurrency,
poolMax, warmSchedule, burst-response tuning) — see Scale to zero.
To bind an existing Postgres, add a database block — see
Databases.
3 · Build, push, deploy
deploy is the default command — build → push → apply the NextApp CR. Validation runs
automatically when the config loads.
# build + push (digest is resolved automatically) and apply the NextApp CR
$ kn-next deploy --registry registry.example.com/acme
✓ image registry.example.com/acme@sha256:9f1c...
✓ NextApp/acme applied
✓ url https://acme.apps.example.com (scaled to 0)kn-next deploy flags: -r/--registry, -b/--bucket, -t/--tag, -n/--namespace,
--skip-build, --skip-upload, --dry-run (print the CR without applying), -h/--help,
-v/--version.
Then watch the rollout to real readiness — status exits non-zero if the app fails to come up, so
this pair works as a CI gate:
$ kn-next status acme --watch # polls until Ready=True (bounded)The operator is the source of truth. The CLI only ever applies the NextApp CR. The Go
operator reconciles it into a Knative Service — wiring autoscaling, optionally the bytecode-cache
volume, and rejecting any image that is not digest-pinned. See
Operator & the NextApp CRD.
The whole CLI at a glance
Every command below is npx kn-next <verb>. Anything that is not one of these words runs the
default deploy flow. Full flag tables are on the CLI reference.
| Command | What it does | What it writes |
|---|---|---|
npx kn-next deploy | Build → push → apply the digest-pinned NextApp CR. The default. | Applies the NextApp CR; with object storage configured, also uploads static assets to your bucket. |
npx kn-next doctor | Cluster-prereq preflight: CRD, operator, admission webhook, ingress class, Knative Serving. | Nothing — read-only. |
npx kn-next status | The operator's honest Ready / Degraded / Reconciling / DatabaseReady conditions. | Nothing — read-only. |
npx kn-next rollback | Pin serving traffic to a prior Knative Revision (or clear the pin). | One merge-patch of spec.traffic on the NextApp CR. |
npx kn-next db bind | Bind an existing Postgres Secret as DATABASE_URL. | One merge-patch of spec.database.secretRef on the NextApp CR. |
npx kn-next db migrate | Apply pending drizzle migrations against the writer, once. | Your database only — no cluster write. |
npx kn-next gc | Reap superseded _next/static/<build-id>/ prefixes (over-keep, never over-delete). | With object storage configured, deletes old asset prefixes from your bucket (reads the CR only); with none, reports there is nothing to reap. |
npx kn-next doctor # before your first deploy
npx kn-next deploy -r registry.example.com/acme # build → push → apply
npx kn-next status acme --watch # poll until Ready=True
npx kn-next rollback acme --to acme-00002 # pin 100% to a prior revision
npx kn-next db bind acme --secret acme-db # DATABASE_URL from a Secret
npx kn-next db migrate --dir ./drizzle # writer-only, idempotent
npx kn-next gc --dry-run # print the reap/keep plan onlybuild, cleanup, preview, and loadtest are not kn-next subcommands — they ship as
directly runnable entries in the package. See
Directly runnable entries.