Environment Variables
Securing secrets and exposing public keys.
The NEXT_PUBLIC Prefix
Next.js seamlessly loads .env, .env.local, .env.development, and .env.production files into Node's process.env.
By default, all environment variables are only available in the Node.js/Edge environments (Server Components, Route Handlers, Middleware).
To expose a variable to the browser (Client Components), you must explicitly prefix it with NEXT_PUBLIC_.
Preventing Catastrophic Leaks
If you accidentally bundle your STRIPE_SECRET_KEY or DATABASE_URL into the client's JavaScript, a malicious user can extract it by opening the browser DevTools.
Next.js enforces security by default. It physically strips non-public variables from the client bundle during compilation, replacing them with undefined.
Implementation
env
# .env.local
STRIPE_SECRET_KEY=sk_test_12345
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_12345
typescript
// Server Component (app/page.tsx)
export default function Page() {
// This works perfectly on the server.
const secret = process.env.STRIPE_SECRET_KEY;
return <ClientComponent publishableKey={process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY} />
}
typescript
// Client Component (components/ClientComponent.tsx)
'use client';
export default function ClientComponent() {
// This will be undefined in the browser!
const secret = process.env.STRIPE_SECRET_KEY;
// This works fine.
const pubKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
}
Environment Variable Compiler
Watch how the Next.js compiler treats private vs public environment variables during a build.
// Returns undefined in browser!
const key = process.env.STRIPE_SECRET_KEY;
return <Stripe apiKey={key} />;
}
// Safely bundled to the client
const key = process.env.NEXT_PUBLIC_STRIPE_PUB;
return <Stripe apiKey={key} />;
}
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Always use the
NEXT_PUBLIC_prefix for variables the browser needs (e.g., Supabase anon key, Stripe publishable key). - Never use
NEXT_PUBLIC_for database passwords, API secrets, or service account keys. .env.localis for local secrets and should be added to.gitignore.
Done with this concept?
Mark it complete to track your progress. No login needed.