Preview environments for full-stack Next.js
When Next.js is the whole app — App Router UI, Route Handlers and Server Actions as the backend, its own database — every pull request gets the entire thing live: built with output: 'standalone', database migrated and seeded, running as a real Node server behind its own HTTPS URL. No separate API. No serverless guesswork.
- ✓ Standalone Node server
- ✓ Migrated & seeded DB
- ✓ Server Actions & Route Handlers
A standalone Next app is a backend you have to host
The moment your Next.js app talks to its own database through Route Handlers, Server Actions and Server Components, a meaningful preview isn't a static bundle on a CDN — it's a Node build, a real migrated-and-seeded database, env vars split across server and browser, and auth callback URLs that move with every environment.
Static previews can't reach a database
A CDN preview renders the UI but every Server Action and app/api route 500s — there's no Node runtime and no database behind it to actually exercise the feature.
Shared databases poison reviews
Point two open PRs at one staging Postgres and a schema change in one branch breaks the other. Nobody trusts what the seeded data is supposed to look like.
Env split & auth URLs drift
NEXT_PUBLIC_* bakes into the browser bundle at build time while secrets stay server-side — and NEXTAUTH_URL has to match the exact origin, which changes per environment.
What every full-stack Next.js preview includes
Each branch boots the complete app on its own VPS — the standalone Node server, its database, Redis and background work — wired together and served on one origin.
next build with output: 'standalone', run via node server.js — full SSR and streaming.app/api and actions run in the same process as the UI — the backend ships with the build.NEXT_PUBLIC_* and NEXTAUTH_URL wired to that environment's origin.The env split Next.js forces, set per environment
Next.js bakes NEXT_PUBLIC_* into the client bundle at build time and keeps everything else server-only. We render both halves against the environment's own URL and services, so the boundary is correct without you hand-editing it per branch.
Browser bundle
NEXT_PUBLIC_*
- The environment's public HTTPS URL
- Analytics / feature-flag client keys
- Anything safe to ship to the client
Server only
never bundled
- Database & Redis connection strings
AUTH_SECRETand OAuth provider secretsNEXTAUTH_URLpinned to this origin
Exactly the steps you'd run by hand
Declare your install, migrate and build commands once. We run them in a clean container on every push, against this environment's own database — no bespoke CI YAML, no SSH.
# on every push to the branch npm ci npx prisma migrate deploy && npx prisma db seed # isolated DB, real data npm run build # next build, output: 'standalone' node .next/standalone/server.js # long-lived Node server ✓ ready https://acme-dashboard-pr-214.admn.cloud
From branch to shareable URL in three steps
- 01
Connect the repo
Point ADMN at your Next.js repository and declare your install, migrate/seed and build commands plus a database template — once.
- 02
Pick a branch
Choose any branch or PR. We provision a dedicated VPS, migrate and seed an isolated database, build standalone and start the Node server.
- 03
Share the URL
A real HTTPS environment where Server Actions, Route Handlers and auth all work. Renew the lease to keep it, or let it expire and tear down clean.
Full-stack Next.js preview environments, answered
Do Prisma or Drizzle migrations and seeds run on boot?
Yes. Each environment gets its own isolated database, and your declared migrate step runs against it before the app starts — `npx prisma migrate deploy` and `npx prisma db seed`, or `drizzle-kit migrate` plus your seed script. Because the database is fresh per branch, `prisma db push` works too for schemas that change a lot mid-review. The seed runs every boot, so reviewers open onto realistic data instead of empty tables.
Are Route Handlers and Server Actions supported?
They are the whole point. Your `app/api/*` Route Handlers and your Server Actions run as part of the same Node process that renders pages — no separate API service, no second deploy. React Server Components that read straight from the database work exactly as they do in production, because the database is right there in the environment.
What happens to ISR and on-demand revalidation in a short-lived environment?
A fresh ephemeral environment starts with a cold cache, which is what you want for review: the first request to an ISR route renders against current data, and your `revalidatePath` / `revalidateTag` calls behave normally for the life of the environment. When the lease expires the whole cache is destroyed with it, so nothing leaks between branches.
Do you run the standalone Node server from next build?
Yes. Set `output: 'standalone'` in next.config and we run `node .next/standalone/server.js` as a long-lived Node server behind the HTTPS URL — not a static export and not a serverless shim. That means full SSR, streaming, Route Handlers and Server Actions all behave like a normal Node deployment, with the static and public assets copied alongside.
Which database can my Next.js app use?
Postgres, MySQL or MongoDB — provisioned isolated per environment and reachable over the private network. Pair it with whatever ORM your app already uses (Prisma, Drizzle, Mongoose). Redis is provisioned too, for sessions, rate limiting or caching, and the connection strings are injected as server-only env vars.
How do NextAuth / Auth.js callback URLs work per environment?
Every environment has a stable, unique HTTPS URL on admn.cloud, so we wire `NEXTAUTH_URL` (or `AUTH_URL`) and `NEXT_PUBLIC_*` values to that URL automatically. Server-only secrets like `AUTH_SECRET` and provider keys stay server-side and never reach the browser bundle. You still add each environment URL as an allowed callback in your OAuth provider, or use a wildcard if your provider supports it.
Ship your next full-stack Next.js PR with a live URL
Connect GitHub and get the whole app — Node server, migrated and seeded database, env wired — live for every branch, then destroyed without a trace.
