Environment variables in Next.js — the beginner guide

Understand .env.local, NEXT_PUBLIC_ prefix, server-only secrets, and how to set variables on Vercel. Simple explanations with examples for every scenario.

Why environment variables?

API keys, database URLs, and secrets should never be in your code. If you push a Stripe key to GitHub, anyone can use it. Environment variables keep secrets out of your code and let you use different values for local development vs. production.


Step 1: Create .env.local

Create a file called .env.local in your project root. Add your keys:

.env.local
# .env.local — this file is NOT pushed to GitHub
STRIPE_SECRET_KEY=sk_test_xxx
RESEND_API_KEY=re_xxx
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbG...

.env.local is automatically in .gitignore — it never gets pushed to GitHub. Each developer has their own copy.


Step 2: The NEXT_PUBLIC_ rule

This is the most important thing to understand:

  • With NEXT_PUBLIC_ prefix → available in the browser (client components) AND on the server
  • Without prefix → only available on the server (API routes, server components)
The rule
// ✅ This works everywhere (client + server)
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;

// ✅ This works only on the server (API routes, server components)
const secret = process.env.STRIPE_SECRET_KEY;

// ❌ This is undefined in client components!
// "use client"
const broken = process.env.STRIPE_SECRET_KEY; // → undefined

Rule of thumb: if users should never see the value (API secrets, webhook secrets), do NOT add NEXT_PUBLIC_. If the browser needs it (Supabase URL, app URL), add the prefix.


Step 3: Use them in code

Usage examples
// In a server component or API route
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: "2023-08-16",
});

// In a client component
"use client";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;

The ! after process.env.STRIPE_SECRET_KEY tells TypeScript "I know this exists". If you want to be safer, check first:

Safe check
if (!process.env.STRIPE_SECRET_KEY) {
  throw new Error("STRIPE_SECRET_KEY is not set");
}

Step 4: Set variables on Vercel

When you deploy to Vercel, .env.local doesn't exist on the server. You need to add each variable in the Vercel dashboard:

  • Go to your project on Vercel → SettingsEnvironment Variables
  • Add each key and value
  • Choose which environments: Production, Preview, Development
  • Redeploy after adding — changes only apply to new deployments

Quick reference

.env.local reference
# Server only (never visible to users)
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
RESEND_API_KEY=re_...

# Available in browser + server
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
NEXT_PUBLIC_APP_URL=https://yourapp.com

All env vars documented

Delfy's documentation lists every environment variable you need, where to get it, and whether it's public or secret. Copy the template and fill in your keys.

See pricing
Environment variables in Next.js — the beginner guide | Delfy.dev Blog