Hirefullstack – Software Engineering & IT-Beratung aus Berlin
← Back to overview
Core 10 min read

Environment & deployment

Secrets that stay secret – and the way out into the world

In one sentence

Only variables prefixed with NEXT_PUBLIC_ reach the browser. Everything else stays on the server – which is where it belongs.

Environment variables

.env.local
DATABASE_URL="postgres://…"          # stays on the server
STRIPE_SECRET_KEY="sk_live_…"        # stays on the server

NEXT_PUBLIC_SITE_URL="https://example.com"   # reaches the browser
NEXT_PUBLIC_PLAUSIBLE_ID="example.com"       # reaches the browser

The rule for Environment variablesValues from `.env`. Only those starting with `NEXT_PUBLIC_` reach the browser – everything else stays on the server. is simple: the NEXT_PUBLIC_ prefix makes a value public. Anything without it is simply undefined in client components.

Pitfall NEXT_PUBLIC_ is not a formality

The value is baked into the JavaScript that anyone can download. A key with that prefix is therefore published – even if it only appears in one seemingly unremarkable file.

files.txt
.env                 for everyone, in the repository (harmless values only!)
.env.local           your local secrets – belongs in .gitignore
.env.production      for the production build

On the server (Vercel, Docker, …) you set them in the dashboard
or as environment variables – not as a file in the image.
Tip Preventing accidental imports

The server-onlyA tiny package that breaks the build if a file accidentally ends up in the browser. Protection for code holding secrets. package fails the build the moment a file holding secrets is imported by a client component. One import "server-only"; at the top of the file rules out a whole class of mistake.

What the build produces

build.txt
npm run build

  .next/            the result
    static/         files with a hash in the name, cacheable forever
    server/         the server-side part

npm run start       starts the Node server on port 3000

Important: NEXT_PUBLIC_ variables are baked in at build time, not read at start-up. If you use the same image for staging and production you can no longer change them – you need a separate build per environment.

Where to put it

options.txt
Vercel        same team as Next.js, everything without configuration
              server actions, ISR, image optimisation just work

Own Node      npm run build && npm run start behind a reverse proxy
              full control, you handle scaling and caching

Docker        output: "standalone" in next.config.js produces a
              slim image with only the required dependencies

Static        output: "export" – only if you use NO server features.
              No ISR, no server actions, no middleware.
Careful output: export is a one-way street

A purely static export sounds tempting but switches off everything you use Next.js for: server actions, revalidation, image optimisation, middleware. Fine for a documentation site – otherwise rarely the right call.

Before the first deploy

Reach for it when …
  • +

    Run npm run build locally and check the symbol column

  • +

    Enter every secret in the target environment – not in the repository

  • +

    Design an error page and a 404

  • +

    Add robots.ts and sitemap.ts

Skip it when …
  • Only ever having tested in development mode

  • NEXT_PUBLIC_ for something that should stay secret

  • Accidentally committing .env.local

In more depth: Node or edge optional

Server-side code runs in Node by default. For individual routes you can switch to the Edge runtimeA lightweight execution environment close to the user. Quick to start, but can do less than Node. – quicker to start, closer to the user, but with fewer capabilities.

runtime.ts
export const runtime = "edge";     // in a page.tsx or route.ts

// Edge can:     fetch, Web Crypto, streams
// Edge cannot:  fs, net, most database drivers
Good to know When in doubt, Node

Edge pays off for small, frequently called endpoints without a database – redirects, feature flags, simple checks. Anything touching the database stays in Node. Middleware always runs in the edge environment anyway.

Does it stick?

4 questions on this lesson. Wrong answers show up in your stats.

Hirefullstack

Need React firepower on your team?

We have been building React and Next.js applications for clients across Germany for years – as a single expert, as reinforcement for an existing team, or as a complete Scrum team.

Talk about your project →