Environment Variables

Store config and secrets in .env files; prefix with NEXT_PUBLIC_ only for values safe to expose.

SyntaxNEXT_PUBLIC_* is exposed to the browser; everything else is server-only.

Next.js reads environment variables from .env files automatically. The key rule is about exposure:

  • Plain variables (e.g. DATABASE_URL) are server-only — never sent to the browser.
  • Variables prefixed NEXT_PUBLIC_ are inlined into client code and visible to anyone.

So only public, non-secret values should get the NEXT_PUBLIC_ prefix.

Example

Example · bash
# .env.local
DATABASE_URL=postgres://user:pass@localhost/db   # server only
NEXT_PUBLIC_SITE_URL=https://example.com          # exposed to browser

# Reading them in code:
// server component / action:  process.env.DATABASE_URL
// client component:          process.env.NEXT_PUBLIC_SITE_URL

When to use it

  • A developer stores a database connection string in .env.local so it is never committed to version control.
  • A public Stripe publishable key is prefixed with NEXT_PUBLIC_ so the client-side checkout component can read it safely.
  • A CI/CD pipeline sets production secrets as environment variables on the server so .env files need not be deployed.

More examples

Environment variable files

Variables without NEXT_PUBLIC_ are server-only; those with it are embedded in the client bundle.

Example · bash
# .env.local (gitignored — development secrets)
DATABASE_URL=postgres://user:pass@localhost/mydb
STRIPE_SECRET_KEY=sk_test_...

# .env (committed — non-secret defaults)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_STRIPE_KEY=pk_test_...

Read server-side env var

Server code accesses env vars via process.env at runtime; they are never sent to the client.

Example · ts
// app/api/db/route.ts (Server Component or Route Handler)
import { db } from '@/lib/db';

export async function GET() {
  // process.env.DATABASE_URL is available server-side only
  const count = await db.user.count();
  return Response.json({ count });
}

Client-safe public variable

NEXT_PUBLIC_ variables are replaced with their literal values at build time and are visible in the browser.

Example · ts
'use client';
// NEXT_PUBLIC_ vars are inlined at build time
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

export default function ApiStatus() {
  return <p>API: {apiUrl}</p>;
}

Discussion

  • Be the first to comment on this lesson.