This example demonstrates how to build and run a Next.js 15 application using the experimental build pipeline — specifically the compile and generate-env build modes — to produce an image that does not include pre-rendered static pages, but still supports ISR (Incremental Static Regeneration) at runtime.
Normally, next build generates static HTML for pages — which means your database or API gets hit at build time.
That’s often a problem when:
-
❌ Your database isn’t available during CI/CD builds
-
❌ You don’t want to use live credentials in your build environment
-
❌ Your data changes frequently, so static pre-generation doesn’t make sense
With experimental compile mode, Next.js skips HTML generation and compiles only the server code.
ISR still works at runtime, so pages are generated on-demand — not during build.
You get:
-
✅ No DB or API calls during build
-
✅ ISR still works dynamically at runtime
-
✅ Smaller Docker images
-
✅ No need for live DB connections in CI
-
✅ Runtime env injection via generate-env
Command Purpose
npx next build --experimental-build-mode compile
- Compiles server code without static HTML output
npx next build --experimental-build-mode generate-env
- Injects the environment variables into the bundle
When using NEXT_PUBLIC_ variables, where and when you inject them matters.
If your variable is only used on the server
you don’t need generate-env — just compile the app:
npx next build --experimental-build-mode compileand pass the env vars at runtime:
NEXT_PUBLIC_EXAMPLE_ENV="Hello from runtime 👋" npx next start`✅ Works in Docker and local Node environments.
✅ Env var is available in all server-side code at runtime.
If your variable is used in the browser (inside a Client Component or exposed via hydration),
you need to inject it during build using generate-env, like so:
First:
npx next build --experimental-build-mode compilethen
NEXT_PUBLIC_EXAMPLE_ENV="Hello from local runtime 👋" npx next build --experimental-build-mode generate-envThen start the app (no need to pass it again):
npx next start✅ Now the variable is available in both:
- the client bundle (e.g.
process.env.NEXT_PUBLIC_EXAMPLE_ENVin client components) - and the server runtime
You have two options, depending on where your variable needs to be available 👇
If your variable is only used on the server (like inside API routes or Server Components):
docker run -p 3000:3000 \
-e NEXT_PUBLIC_EXAMPLE_ENV="Hello from runtime 🐳" \
next-no-static-isr✅ Available in server-side code (Node runtime)
❌ Not available to the client bundle
✅ Works great for most backend-only values
So if your app just needs it for database queries, server logs, etc. — this is all you need.
If your variable needs to appear on the client side (e.g., displayed in the UI),
you must pass it during the build so that Next.js can include it in the generated env manifest:
docker build \
--build-arg NEXT_PUBLIC_EXAMPLE_ENV="Hello from Docker build 🧱" \
-t next-no-static-isr .Then run normally:
docker run -p 3000:3000 next-no-static-isr✅ Available in both client and server code