Just keeping your API key out of Git isn't enough. Any variable with the NEXT_PUBLIC_ prefix can end up in the browser bundle, so it's no longer a secret. The first thing to figure out is where the variable is actually used.
The key idea
.env.local is for local secrets, so it should never be committed. A server-only variable like DATABASE_URL should have no prefix at all. Reserve NEXT_PUBLIC_ for things the browser genuinely needs, like a public analytics id. Validate at app startup so a missing variable doesn't crash things mid-runtime. On top of that, your production checklist should cover user input validation, output escaping, security headers, CSP, HTTPS, and keeping dependencies patched.
Let's try it together
// .env.local (Git ထဲမထည့်ပါနှင့်)
DATABASE_URL="postgres://..."
NEXT_PUBLIC_APP_NAME="Myanmar Notes"
// lib/env.ts
import "server-only";
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) throw new Error("DATABASE_URL is required");
export const env = { databaseUrl };
// .env.example
DATABASE_URL=
NEXT_PUBLIC_APP_NAME=Myanmar NotesHow the code works
The env helper catches a missing DATABASE_URL early. Client Components must never import this module. .env.example only lists key names, never real values.
Secrets stay server-only, and a clear error appears at startup if the environment isn't fully configured.5-Minute Try-It
Split your project's environment variables into public and server-only groups, then create a .env.example for it.
Next.js — Environment Variables — Next.js