[{"data":1,"prerenderedAt":377},["ShallowReactive",2],{"blog-how-to/hide-api-keys":3},{"id":4,"title":5,"body":6,"category":358,"date":359,"dateModified":359,"description":360,"draft":361,"extension":362,"faq":363,"featured":361,"headerVariant":364,"image":363,"keywords":363,"meta":365,"navigation":366,"ogDescription":367,"ogTitle":363,"path":368,"readTime":363,"schemaOrg":369,"schemaType":370,"seo":371,"sitemap":372,"stem":373,"tags":374,"twitterCard":375,"__hash__":376},"blog/blog/how-to/hide-api-keys.md","How to Hide API Keys - Secure Your Secrets",{"type":7,"value":8,"toc":344},"minimark",[9,13,18,22,28,33,36,39,43,81,101,130,150,170,215,234,238,269,275,281,306,325],[10,11],"category-badge",{"category":12},"How-To Guide",[14,15,17],"h1",{"id":16},"how-to-hide-api-keys","How to Hide API Keys",[19,20,21],"p",{},"The essential guide to keeping your secrets out of your code",[23,24,25],"tldr",{},[19,26,27],{},"TL;DR:\nMove all API keys to environment variables stored in\n.env\nfiles. Add\n.env\nto your\n.gitignore\nimmediately. In production, use your hosting platform's secret management (Vercel, Netlify, Railway all have built-in tools). Never put secret keys in frontend code.",[29,30,32],"h2",{"id":31},"why-this-matters","Why This Matters",[19,34,35],{},"Exposed API keys are the most common security issue in vibe-coded apps. According to GitGuardian, over 10 million secrets were exposed in public GitHub repos in 2023 alone. When AI generates code, it often hardcodes example keys or uses placeholder values that you might forget to remove.",[19,37,38],{},"The consequences can be severe: compromised Stripe keys can drain your bank account, exposed OpenAI keys can rack up thousands in charges, and leaked database credentials can expose all your user data.",[29,40,42],{"id":41},"step-by-step-guide","Step-by-Step Guide",[44,45,47,52,55,66],"step",{"number":46},"1",[48,49,51],"h3",{"id":50},"identify-all-your-api-keys","Identify all your API keys",[19,53,54],{},"Search your codebase for hardcoded secrets:",[56,57,62],"pre",{"className":58,"code":60,"language":61},[59],"language-text","# Search for common key patterns\ngrep -r \"sk_live\\|sk_test\\|api_key\\|apiKey\\|API_KEY\" --include=\"*.ts\" --include=\"*.js\" --include=\"*.tsx\"\n\n# Search for specific services\ngrep -r \"OPENAI\\|STRIPE\\|SUPABASE\\|FIREBASE\" --include=\"*.ts\" --include=\"*.js\"\n","text",[63,64,60],"code",{"__ignoreMap":65},"",[19,67,68,69,72,73,76,77,80],{},"Look for anything that looks like a key: long random strings, keys starting with ",[63,70,71],{},"sk_",", ",[63,74,75],{},"pk_",", or containing ",[63,78,79],{},"secret",".",[44,82,84,88,95],{"number":83},"2",[48,85,87],{"id":86},"create-a-envlocal-file","Create a .env.local file",[19,89,90,91,94],{},"In your project root, create a ",[63,92,93],{},".env.local"," file:",[56,96,99],{"className":97,"code":98,"language":61},[59],"# .env.local - Never commit this file!\n\n# Database\nDATABASE_URL=postgresql://user:password@localhost:5432/mydb\n\n# Stripe (secret key - server only)\nSTRIPE_SECRET_KEY=sk_test_51xxxxx\n\n# OpenAI\nOPENAI_API_KEY=sk-xxxxx\n\n# Supabase (these are safe for client)\nNEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxxx\n",[63,100,98],{"__ignoreMap":65},[44,102,104,108,115,121,124],{"number":103},"3",[48,105,107],{"id":106},"add-env-files-to-gitignore","Add .env files to .gitignore",[19,109,110,111,114],{},"Open or create ",[63,112,113],{},".gitignore"," and add these lines:",[56,116,119],{"className":117,"code":118,"language":61},[59],"# Environment files - NEVER commit these\n.env\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n.env.production\n\n# Keep the example file for documentation\n!.env.example\n",[63,120,118],{"__ignoreMap":65},[19,122,123],{},"Run this to make sure .env files aren't already tracked:",[56,125,128],{"className":126,"code":127,"language":61},[59],"git rm --cached .env .env.local 2>/dev/null || true\n",[63,129,127],{"__ignoreMap":65},[44,131,133,137,144],{"number":132},"4",[48,134,136],{"id":135},"create-an-example-file-for-documentation","Create an example file for documentation",[19,138,139,140,143],{},"Create ",[63,141,142],{},".env.example"," with placeholder values (this file IS safe to commit):",[56,145,148],{"className":146,"code":147,"language":61},[59],"# .env.example - Copy to .env.local and fill in real values\nDATABASE_URL=postgresql://user:password@localhost:5432/mydb\nSTRIPE_SECRET_KEY=sk_test_your_key_here\nOPENAI_API_KEY=sk-your_key_here\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key_here\n",[63,149,147],{"__ignoreMap":65},[44,151,153,157,164],{"number":152},"5",[48,154,156],{"id":155},"update-your-code-to-use-environment-variables","Update your code to use environment variables",[19,158,159,160,163],{},"Replace hardcoded keys with ",[63,161,162],{},"process.env",":",[56,165,168],{"className":166,"code":167,"language":61},[59],"// BEFORE - Hardcoded (dangerous!)\nconst stripe = new Stripe('sk_test_51xxxxx');\n\n// AFTER - Using environment variable (safe)\nconst stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n// Add validation to catch missing keys early\nif (!process.env.STRIPE_SECRET_KEY) {\n  throw new Error('Missing STRIPE_SECRET_KEY environment variable');\n}\n",[63,169,167],{"__ignoreMap":65},[44,171,173,177,180],{"number":172},"6",[48,174,176],{"id":175},"configure-production-secrets-in-your-hosting-platform","Configure production secrets in your hosting platform",[19,178,179],{},"Never deploy .env files to production. Instead, configure secrets in your platform:",[181,182,183,191,197,203,209],"ul",{},[184,185,186,190],"li",{},[187,188,189],"strong",{},"Vercel:"," Project Settings → Environment Variables",[184,192,193,196],{},[187,194,195],{},"Netlify:"," Site Settings → Environment Variables",[184,198,199,202],{},[187,200,201],{},"Railway:"," Service → Variables",[184,204,205,208],{},[187,206,207],{},"Render:"," Service → Environment",[184,210,211,214],{},[187,212,213],{},"Cloudflare Pages:"," Settings → Environment Variables",[216,217,218,221,228],"warning-box",{},[19,219,220],{},"Important: Public vs Private Keys",[19,222,223,224,227],{},"In Next.js, only variables prefixed with ",[63,225,226],{},"NEXT_PUBLIC_"," are exposed to the browser. Secret keys should NEVER have this prefix:",[56,229,232],{"className":230,"code":231,"language":61},[59],"# WRONG - This exposes the secret to everyone\nNEXT_PUBLIC_STRIPE_SECRET=sk_live_xxxxx\n\n# CORRECT - This stays server-side only\nSTRIPE_SECRET_KEY=sk_live_xxxxx\n\n# CORRECT - Public key, safe for browser\nNEXT_PUBLIC_STRIPE_PUBLISHABLE=pk_live_xxxxx\n",[63,233,231],{"__ignoreMap":65},[29,235,237],{"id":236},"how-to-verify-your-keys-are-hidden","How to Verify Your Keys Are Hidden",[239,240,241,251,257,263],"ol",{},[184,242,243,246,247,250],{},[187,244,245],{},"Check your git status:"," Run ",[63,248,249],{},"git status"," and make sure no .env files appear",[184,252,253,256],{},[187,254,255],{},"Search your bundle:"," Build your app, then search the output for key patterns",[184,258,259,262],{},[187,260,261],{},"Check network requests:"," Open DevTools Network tab and look for keys in requests",[184,264,265,268],{},[187,266,267],{},"View page source:"," Search for keys in your compiled HTML/JS",[56,270,273],{"className":271,"code":272,"language":61},[59],"# Search built files for leaked keys\ngrep -r \"sk_live\\|sk_test\" .next/ dist/ build/ 2>/dev/null\n",[63,274,272],{"__ignoreMap":65},[276,277,278],"tip-box",{},[19,279,280],{},"Pro Tip:\nUse a tool like\nCheckYourVibe\nto automatically scan your codebase for exposed secrets before every deploy.",[282,283,284,291,297],"faq-section",{},[285,286,288],"faq-item",{"question":287},"What if I already committed a key to git?",[19,289,290],{},"Assume it's compromised. Immediately rotate the key in the service's dashboard, then update your environment variables. Don't waste time trying to remove it from git history; the key should be considered public.",[285,292,294],{"question":293},"Are Supabase anon keys safe to expose?",[19,295,296],{},"Yes, Supabase anon keys are designed to be public. They only work with Row Level Security policies, which is why RLS is so important. The service_role key, however, must stay secret.",[285,298,300],{"question":299},"Can I use the same .env file for development and production?",[19,301,302,303,305],{},"You shouldn't. Use ",[63,304,93],{}," for development with test keys, and configure separate production secrets in your hosting platform. This prevents accidentally using test data in production.",[19,307,308,311,316,317,316,321],{},[187,309,310],{},"Related guides:",[312,313,315],"a",{"href":314},"/blog/how-to/rotate-api-keys","How to Rotate API Keys"," ·\n",[312,318,320],{"href":319},"/blog/how-to/check-exposed-keys","How to Check for Exposed Keys",[312,322,324],{"href":323},"/blog/how-to/environment-variables","How to Use Environment Variables",[326,327,328,334,339],"related-articles",{},[329,330],"related-card",{"description":331,"href":332,"title":333},"Step-by-step guide to setting up Supabase Auth securely. Configure authentication, handle sessions, integrate with RLS, ","/blog/how-to/supabase-auth","How to Set Up Supabase Auth Securely",[329,335],{"description":336,"href":337,"title":338},"Learn to write effective Row Level Security policies in Supabase. Real examples for profiles, posts, teams, and multi-te","/blog/how-to/supabase-rls-policies","How to Write Supabase RLS Policies",[329,340],{"description":341,"href":342,"title":343},"Verify your Row Level Security policies work correctly. Learn SQL testing methods, browser testing, and automated testin","/blog/how-to/test-supabase-rls","How to Test Supabase RLS Policies",{"title":65,"searchDepth":345,"depth":345,"links":346},2,[347,348,357],{"id":31,"depth":345,"text":32},{"id":41,"depth":345,"text":42,"children":349},[350,352,353,354,355,356],{"id":50,"depth":351,"text":51},3,{"id":86,"depth":351,"text":87},{"id":106,"depth":351,"text":107},{"id":135,"depth":351,"text":136},{"id":155,"depth":351,"text":156},{"id":175,"depth":351,"text":176},{"id":236,"depth":345,"text":237},"how-to","2026-01-16","Step-by-step guide to hiding API keys in your web app. Use environment variables, .gitignore, and platform secrets to keep your keys safe from exposure.",false,"md",null,"yellow",{},true,"Step-by-step guide to hiding API keys using environment variables and platform secrets.","/blog/how-to/hide-api-keys","[object Object]","HowTo",{"title":5,"description":360},{"loc":368},"blog/how-to/hide-api-keys",[],"summary_large_image","21XgDY1r5bOET4H3V5XyX_OuIxKmvpp---BumqZ2M1U",1775843918546]