TL;DR
Create a .env file for your API keys, add it to .gitignore, and access keys only from server-side code. For production, add keys to your hosting platform's environment settings. Never put secret keys in frontend JavaScript or commit them to GitHub.
API keys are the passwords your app uses to talk to services like Stripe, OpenAI, and Supabase. When they're exposed in your code, attackers can use them to rack up charges on your account or steal your data.
This guide walks through the correct way to handle API keys, step by step. It takes about 10 minutes to set up properly and saves you from potentially expensive mistakes.
Why This Matters
Before we get into the how, let's be clear about the stakes:
- OpenAI key exposed: Attackers run up thousands in API charges
- Stripe secret key exposed: Access to customer payment data
- AWS credentials exposed: Crypto mining on your account ($10K+ bills)
- Supabase service key exposed: Complete database access bypassing all security
These aren't hypothetical. They happen every day to founders who didn't know any better.
Create a .env File
In your project root, create a file called .env (just the extension, no filename):
# .env
OPENAI_API_KEY=sk-proj-abc123xyz789...
STRIPE_SECRET_KEY=sk_live_abc123...
SUPABASE_SERVICE_ROLE_KEY=eyJhbG...
DATABASE_URL=postgresql://user:pass@host/db
Each line has a variable name, an equals sign, and the value. No quotes needed in most cases.
Add .env to .gitignore
Open or create a .gitignore file in your project root and add:
# .gitignore
.env
.env.local
.env.*.local
.env.production
This prevents git from tracking your environment files. They'll never be committed or pushed to GitHub.
Already Committed a Key? If you've already committed a .env file, adding it to .gitignore won't remove it from history. You need to rotate that key immediately and consider it compromised.
Access Keys from Server-Side Code
The critical rule: secret keys should only be accessed from code that runs on the server. Here's how this looks in different frameworks:
Next.js
// app/api/chat/route.js (Server-side API route)
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
export async function POST(request) {
// This runs on the server, key is safe
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [...]
});
return Response.json(completion);
}
Express.js
// server.js
require('dotenv').config();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/create-payment', async (req, res) => {
// Server-side, key is safe
const session = await stripe.checkout.sessions.create({...});
res.json({ url: session.url });
});
Configure Production Environment
Your .env file only works locally. For production, add keys to your hosting platform:
| Platform | Where to Add Keys |
|---|---|
| Vercel | Project Settings → Environment Variables |
| Netlify | Site Settings → Environment Variables |
| Railway | Project → Variables tab |
| Render | Dashboard → Environment |
| Replit | Secrets (padlock icon in sidebar) |
Add the same variable names and values you have in your local .env file. The platform will inject them at runtime.
Common Mistakes to Avoid
Mistake 1: Using NEXT_PUBLIC_ for Secret Keys
In Next.js, variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Never use this prefix for secret keys:
# BAD - This is visible to anyone
NEXT_PUBLIC_OPENAI_KEY=sk-proj-abc123...
# GOOD - This stays server-side
OPENAI_API_KEY=sk-proj-abc123...
Mistake 2: Calling Secret APIs from the Frontend
You cannot safely use secret keys in React components, even with environment variables:
// BAD - This runs in the browser
function ChatComponent() {
const response = await fetch('https://api.openai.com/v1/chat', {
headers: {
'Authorization': `Bearer ${process.env.OPENAI_KEY}`
}
});
}
// GOOD - Call your own API route instead
function ChatComponent() {
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message })
});
}
Mistake 3: Hardcoding Keys "Just for Testing"
It's tempting to hardcode a key to test quickly. Don't. Set up environment variables from the start:
// BAD - "I'll remove it later" (you won't)
const apiKey = "sk-proj-abc123...";
// GOOD - Always use environment variables
const apiKey = process.env.OPENAI_API_KEY;
How to Verify Your Keys Are Hidden
- Deploy your app to production
- Open browser dev tools (F12)
- Go to the Network tab and look at request headers
- Search in the Sources tab for your key value
- Run a security scan to catch what you might miss
If you can find your secret keys through any of these methods, they're exposed and need to be fixed.
API Key Security Checklist
- Created .env file for local development
- Added .env to .gitignore
- Secret keys accessed only from server-side code
- No NEXT_PUBLIC_ prefix on secret keys
- Production keys added to hosting platform
- No hardcoded keys anywhere in codebase
- Verified keys not visible in browser dev tools
What is the right way to hide API keys?
Store API keys in environment variables, not in your code. Create a .env file for local development, add it to .gitignore so it's never committed, and add the keys to your hosting platform's environment settings for production. Access the keys from server-side code only, never from frontend JavaScript.
Can I put API keys in frontend JavaScript?
No. Any code that runs in the browser can be viewed by users. If you put an API key in React, Vue, or vanilla JavaScript, anyone can find it by opening browser developer tools. API calls requiring secret keys must go through your backend server.
What is a .env file?
A .env file is a simple text file that stores environment variables as key-value pairs. It keeps sensitive values like API keys separate from your code. The file should never be committed to version control and should be listed in your .gitignore file.
What if I already committed my API keys?
Consider those keys compromised. Immediately rotate them by generating new keys in the service's dashboard and revoking the old ones. Then update your code to use environment variables properly. Adding .env to .gitignore won't remove keys from git history.
Check If Your Keys Are Exposed
Run a free security scan to find exposed API keys and other vulnerabilities.
Start Free Scan