Sitemap
Syamkumar S

Syamkumar S

Writer. Builder. AI enthusiast. Exploring technology, creativity, meaningful work, and the journey of building a life with more freedom.

Next.js Environment Variables: The Complete Guide

3 min readSep 22, 2026

--

Press enter or click to view image in full size

Environment variables in Next.js have a rule that trips up nearly every developer at least once: the NEXT_PUBLIC_ prefix is the entire difference between a secret staying secret and being shipped to every visitor's browser.

The Two Types

# .env.local
DATABASE_URL=postgres://... # server-only, never reaches the browser
NEXT_PUBLIC_ANALYTICS_ID=UA-12345 # bundled into client JavaScript, visible to anyone

Anything without NEXT_PUBLIC_ is only accessible in server components, Route Handlers, and Server Actions. Anything with the prefix gets compiled directly into your client-side JavaScript bundle — viewable by opening browser dev tools on any deployed site.

Mistake 1: Putting Secrets in NEXT_PUBLIC_ Variables

NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_... # catastrophic mistake

This exposes your Stripe secret key to literally anyone who opens dev tools. Only ever prefix genuinely public values — analytics IDs, publishable API keys, feature flags meant to be visible.

Mistake 2: Expecting Server Variables in Client Components

'use client';
export default function Widget() {
console.log(process.env.DATABASE_URL); // undefined — always, by design
}

This isn’t a bug — it’s the entire point. If you need a value client-side, it must be explicitly prefixed and intentionally public.

Mistake 3: Not Restarting the Dev Server After Changing .env

Next.js reads environment variables at build/start time, not on every request in development. Adding a new variable and expecting it to appear without restarting next dev is a common source of "why is this undefined" confusion.

Get Syamkumar S’s stories in your inbox

Join Medium for free to get updates from this writer.

Setting Up Environment Files Correctly

.env.local          # local secrets, gitignored, loaded everywhere
.env.development # dev-specific defaults, can be committed
.env.production # production-specific defaults, can be committed

.env.local should always be in .gitignore — it's the file real secrets go in, and it should never be committed regardless of how small the project is.

Validating Environment Variables at Startup

A common production incident: a missing environment variable causes a cryptic failure deep in your app instead of a clear error at startup. Validate early:

// lib/env.js
const required = ['DATABASE_URL', 'OPENAI_API_KEY'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
}

Import this file once at the top of your app’s entry point so missing config fails loudly and immediately, not three requests into production traffic.

Using Environment Variables Across Deployment Platforms

Local .env.local files don't automatically transfer to Vercel, Netlify, or any hosting platform — each requires setting the same variables in its own dashboard or CLI. A common deployment bug is a feature working locally and breaking in production simply because a variable was never added to the hosting platform's environment settings.

Level Up Your Next.js Skills

Bottom Line

The NEXT_PUBLIC_ prefix is the one rule that matters most — everything else about Next.js environment variables follows from understanding that boundary. Validate required variables at startup, keep .env.local out of version control, and remember that local environment files never automatically sync to your hosting platform.

--

--