Security

Securing Environment Variables in Next.js Projects

SyncTonight Team7 min read2 views0 likes

Next.js has a rule that catches a lot of developers off guard: any environment variable prefixed with NEXT_PUBLIC_ gets bundled directly into your client-side JavaScript and shipped to every visitor's browser, in plain text, viewable by anyone who opens dev tools. Any variable without that prefix stays server-only and is never exposed to the browser.

This distinction exists for a real reason — some environment variables genuinely need to be available in browser-side code, like a public API endpoint URL or a publishable Stripe key that's designed to be public. But it means the NEXT_PUBLIC_ prefix is not a convenience setting, it's a security boundary, and accidentally prefixing a secret with it is one of the most common ways real credentials end up leaked in a production build.

The mistake usually happens innocently — a developer adds NEXT_PUBLIC_ to a database connection string or a private API key just to make it 'available everywhere' during local development, without realizing that prefix specifically means 'ship this to every browser that loads the site.' By the time it's caught, the secret may already be baked into a deployed build and cached by a CDN.

The fix starts with an audit: search your entire codebase for NEXT_PUBLIC_ and check every single variable using that prefix. Ask, for each one, whether it would be actually fine for a random visitor to see it in their browser's network tab or bundled JavaScript. If the answer is no, remove the prefix and restructure the code that needs it to run server-side instead — in an API route, a Server Component, or a Server Action.

If you've already deployed a build with a real secret exposed under NEXT_PUBLIC_, removing the prefix and redeploying is necessary but not sufficient — the secret was already shipped to anyone who loaded the site while that build was live, and it may be cached in browsers or CDN edges. Treat it as compromised: rotate the actual credential (generate a new API key, change the database password) rather than assuming removing the variable retroactively protects it.

For genuinely server-only secrets, keep them in .env.local (which Next.js loads automatically and which should always be in .gitignore) and access them only from server-side code — Route Handlers, Server Components, Server Actions, or middleware. Never import a server-only environment variable into a file that also gets used in client components, since bundlers can sometimes include more than expected if the boundary between server and client code isn't clean.

Finally, double-check your deployment platform's own environment variable settings too, not just your local .env files — a variable set as 'available to the browser' in your hosting dashboard (some platforms have their own separate public/private toggle, distinct from the NEXT_PUBLIC_ convention) can leak a secret even if your code never uses the NEXT_PUBLIC_ prefix at all.

Found this helpful?

SyncTonight's tools and guides are free and always will be. If this post saved you some debugging time, a coffee goes a long way — no pressure, just appreciated.

☕ Buy me a coffee

Keep Reading

Also available

We also build websites.

Need a landing page, a full product site, or a custom web app built? We design and develop those too — same speed and no-nonsense approach you see here. Let us know what you're building.

Landing pagesFull websitesWeb appsSaaS MVPsDashboards
Let's talk about your project