explainer

Environment Variables

How secrets reach your app without living in your code — and the two-copies rule behind the most common “works on my laptop” bug.

4 min readthe #1 deploy gotcha

What they actually are

Named values that live next toyour code instead of inside it — think of them as your app's settings drawer. Two kinds of things belong there: secrets (API keys, database passwords — things that must never end up on GitHub) and things that differ between your laptop and your live site.

Your code says “connect using whatever SUPABASE_URLis” — and each place the app runs supplies its own value. Same code everywhere, different settings per place.

The file: .env.local

On your laptop, environment variables live in a file called .env.local in your project's root — one NAME=value per line:

.env.local
NEXT_PUBLIC_SUPABASE_URL=https://abcdefgh.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_xxxxxxxx
SUPABASE_SECRET_KEY=sb_secret_xxxxxxxx

The crucial property: this file is gitignored on purpose. It never gets committed, never gets pushed, never appears on GitHub — even in a public repo. That's the entire trick: code travels, secrets don't.

💡 tipYou'll rarely edit this file by hand. Tell Claude “put these values in .env.local and make sure it's gitignored” and it handles both.

Public vs. secret values

In Next.js, a variable starting with NEXT_PUBLIC_gets baked into the code that ships to visitors' browsers — anyone can see it. That's correct for values designed to be public (Supabase's publishable key is public by design, protected by Row Level Security). Everything without the prefix stays on the server, invisible to browsers.

🔑The naming rule:

Never put NEXT_PUBLIC_in front of a real secret — that one prefix is the difference between “server-only” and “published to every visitor.” If you're unsure about a value, ask Claude: “should this env variable be public or server-only?”

The two-copies rule

Because .env.local never leaves your laptop, your live site knows nothing about it. Every value your app needs exists in two places: the file on your laptop, and your host's settings for the live site:

Vercel projectSettingsEnvironment Variablesadd each oneRedeploy

🩹The #1 deploy gotcha:

“Works on localhost, breaks on Vercel” is almost always a variable that exists in .env.local but was never added in Vercel. When it happens, ask Claude:

paste into Claude Code
List every environment variable this project needs so I can
check they're all set in Vercel.

💡 tipVercel only reads env variables at build time — after adding or changing one, hit Redeploy or the change won't take effect.