Environment Variables and API Keys, Explained for Vibe Coders
Your AI tool asked for an “API key” and told you to “add it to your environment variables”. Then something stopped working, or worse, it worked and your key ended up somewhere public. This guide explains the idea in plain language, then shows where keys go on each platform.
The one-sentence version
An environment variable is a named setting (like STRIPE_SECRET_KEY) that lives outside your code, so your code can say “use whatever value is called X” without the value being written in the file. That lets you keep secrets out of your code, out of GitHub and out of AI chats, and use different values for testing and for the live site.
Two kinds of keys: the ones you can show, and the ones you can’t
Almost every service hands out two kinds of key. Learn to tell them apart and you’ve avoided the most expensive vibe-coding mistake there is.
| Public / publishable | Secret | |
|---|---|---|
| Who may see it | Anyone. It ships inside your web page | Only your server code |
| What it can do | Only what your security rules allow | Usually everything on your account |
| Supabase | Publishable key sb_publishable_… (legacy: anon) | Secret key sb_secret_… (legacy: service_role) |
| Stripe | Publishable key pk_… | Secret key sk_…, restricted key rk_…, webhook secret whsec_… |
| AI providers (OpenAI, Anthropic…) | Usually none | The API key |
Supabase puts it nicely: the publishable key “is taped to the front door, and it only opens the lobby. The secret key is the master key.” A Supabase secret key bypasses Row Level Security completely. (Supabase: API keys) Stripe likewise says only publishable keys are safe to expose. (Stripe: API keys) A leaked AI key means someone else spends your credits.
Heads up: Supabase is deprecating the legacy
anonandservice_rolekeys by the end of 2026. If a tutorial or AI tool tells you to copy a long key that starts witheyJ, it was written for the legacy keys.
The prefix rule: VITE_ and NEXT_PUBLIC_ mean “put this in the browser”
Most AI app builders produce either a Vite app (Lovable, most Bolt projects) or a Next.js app. Both have a special prefix that tells the build tool “copy this value into the JavaScript that every visitor downloads”:
- Vite: variables starting with
VITE_are exposed in client-side code. Vite’s docs say outright thatVITE_*variables “should not contain sensitive information such as API keys”. (Vite: Env variables) - Next.js: variables starting with
NEXT_PUBLIC_are inlined into the JavaScript sent to the browser at build time. Everything without the prefix stays on the server. (Next.js: Environment variables)
So the rule is simple:
# ✅ Fine: these are public by design
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
# ❌ Never do this. The prefix ships your secret to every visitor
VITE_OPENAI_API_KEY=sk-...
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_...
# ✅ Secrets: no public prefix, read only from server code
OPENAI_API_KEY=sk-...
STRIPE_SECRET_KEY=sk_live_...
SUPABASE_SECRET_KEY=sb_secret_...
“But it says undefined in the browser!” That’s the system working. If your browser code needs a secret to call an API, the fix is not to add the prefix. The fix is to move that API call into server code (an API route, a serverless function or an Edge Function) and have the browser call that. Ask your AI tool: “Move the call to [service] into a server-side function so the API key never reaches the browser.”
.env files and Git
Locally, variables usually live in a file called .env or .env.local in your project folder.
- In a normal Vite or Next.js project (including Cursor projects), keep
.env*files with secrets out of Git. Next.js’s default template adds them to.gitignorefor you, and Vite recommends ignoring*.localfiles. - Before your first push, run
git statusand make sure no.envfile with real secrets is listed. - If a secret was ever committed, assume it’s leaked, even if you deleted it later. Git history keeps it. Rotate it (see below).
Lovable is the exception. Lovable needs its .env file committed so builds can read the VITE_ values. That’s fine because that file should only ever contain public values. Secrets go in Lovable’s Secrets manager instead. (Lovable: Secrets)
Where to put keys on each platform
Lovable
- Secrets (backend values) live in More → Cloud → Secrets. They’re encrypted, injected into your Edge Functions and never reach the browser. Values are write-only after saving.
VITE_values live in the project’s.envfile. Lovable rejectsVITE_-prefixed names in Secrets on purpose.- Usually you don’t add secrets by hand. When a feature needs one, Lovable asks for it through a secure input in the chat. Prefer that over pasting keys into a normal message.
Replit
- Open your project, select Tools, then under Setup select Secrets. Click New Secret, enter a Key and Value, then Add Secret. Your code reads it as an environment variable.
- Replit also has a separate Configurations section for non-sensitive settings. Don’t store API keys there.
- Published apps have their own production values: open Publishing, select Adjust settings and find Production app secrets. Check them before you launch. (Replit: Secrets)
Bolt
Bolt keeps API keys in its own Secrets panel while you build. One gotcha: if you export a Bolt project and deploy it somewhere else (like Vercel Drop), the export doesn’t include the values from Bolt’s Secrets panel. You have to recreate each one on the new host and redeploy. (Vercel: Deploy a Bolt.new app with Vercel Drop)
Vercel (for Cursor, Bolt exports, or anything on GitHub)
- Open your project in the Vercel dashboard and select Environment Variables in the sidebar.
- Enter the Name and Value. Choose Secret for keys (write-only after saving) or Config for values that should stay readable.
- Pick which environments it applies to: Production, Preview and/or Development.
- Click Save, then redeploy.
That last step matters: changes to environment variables only apply to new deployments, never to ones that already exist. If you changed a key and “nothing happened”, that’s why. (Vercel: Managing environment variables)
To copy your Vercel Development variables to your machine, run vercel env pull, which writes them into a local .env file. Make sure that file is gitignored. (Vercel: Environment variables)
Use different keys for testing and for real
Give your live site and your test or preview versions different values:
| Variable | Production (live site) | Preview / Development |
|---|---|---|
STRIPE_SECRET_KEY | live key sk_live_… | test key sk_test_… |
| Supabase keys | your real project | a separate staging project if you have one |
| Site URL | https://yourdomain.com | localhost or the preview URL |
This keeps a half-finished preview from charging real cards or writing junk into your real database.
Never paste secrets into AI chat
Treat AI chats like email. Supabase’s own guidance is that secret keys should never travel over chat, email or SMS. (Supabase: API keys) Instead, put the key in the platform’s secret storage and tell the AI the name of the variable: “Use the RESEND_API_KEY environment variable. Don’t ask me for the value.”
If a key leaked: rotate it calmly
- Fix the cause first. Remove the key from your code, your bundle or your repo.
- Create a new key at the provider (Stripe, Supabase, OpenAI…).
- Replace it everywhere it’s used (Vercel env vars, Lovable Secrets, Replit Secrets) and redeploy.
- Confirm everything works with the new key, then delete or revoke the old one. For Supabase secret keys, deleting can’t be undone, so do this step last.
Quick self-check (2 minutes)
- No secret has a
VITE_orNEXT_PUBLIC_prefix - Search your live site’s JavaScript (DevTools → Sources) for
sk_,sb_secret_,service_roleandwhsec_. Nothing should turn up -
.envfiles with secrets are gitignored (except Lovable’s public-only.env) - Production uses live keys and previews use test keys
- You redeployed after your last env var change
Official sources used: Supabase: API keys · Stripe: API keys · Vite: Env variables and modes · Next.js: Environment variables · Lovable: Secrets · Replit: Secrets · Vercel: Managing environment variables · Vercel: Bolt + Vercel Drop. Checked October 2026.
Want the whole launch path in one place?
The Ship It Kit bundles copy-paste prompts, step-by-step deploy guides and a pre-launch checklist for Lovable, Bolt, Cursor and Replit apps. One-time $19.