knext

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 official Next.js Deployment Adapter API — no fork, no custom runtime.

Prerequisites. A Kubernetes cluster with Knative Serving installed, Next.js 16.x, a container registry, and an object-storage bucket (gcs, s3, or minio).

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.

shell
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/.bin

Two optional packages complete the picture — add them only if you need them:

shell
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
PackageWhat it is forCanonical imports
@getknext/coreThe 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/libRuntime 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/dbThe 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.

next.config.ts — Next.js 16.2+
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 name, registry, and a storage block with provider, bucket, and publicUrl.

kn-next.config.ts
import type { KnativeNextConfig } from '@getknext/core';

const config: KnativeNextConfig = {
  name: 'acme',
  registry: 'registry.example.com/acme',
  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
  // runtime: 'bun',  // optional — run the standalone server under Bun, with
  //                  // build-time bytecode precompilation. See /docs/bun-runtime.
};

export default config;

storage.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.

shell
# 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:

shell
$ 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.

CommandWhat it doesWhat it writes
npx kn-next deployBuild → push → apply the digest-pinned NextApp CR. The default.Applies the NextApp CR; uploads static assets to your bucket.
npx kn-next doctorCluster-prereq preflight: CRD, operator, admission webhook, ingress class, Knative Serving.Nothing — read-only.
npx kn-next statusThe operator's honest Ready / Degraded / Reconciling / DatabaseReady conditions.Nothing — read-only.
npx kn-next rollbackPin 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 bindBind an existing Postgres Secret as DATABASE_URL.One merge-patch of spec.database.secretRef on the NextApp CR.
npx kn-next db migrateApply pending drizzle migrations against the writer, once.Your database only — no cluster write.
npx kn-next gcReap superseded _next/static/<build-id>/ prefixes (over-keep, never over-delete).Deletes old asset prefixes from your bucket; reads the CR only.
shell
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 only

build, cleanup, preview, and loadtest are not kn-next subcommands — they ship as directly runnable entries in the package. See Directly runnable entries.

On this page