{"name":"set-up-env-variables-and-secrets","description":"Sets up environment variables and secrets safely - a .env.local that git ignores, a committed .env.example, values added on the host per environment, browser-safe prefixes only for public values, and a plan to rotate a key that leaked. Use when the user asks where to put API keys, how .env files work, or committed a secret key to git by mistake.","category":"deployment","tags":["secrets","security","hosting"],"models":["any"],"proven":false,"passing_families":0,"model_testing":"Not yet model-tested; testing Jan 2027","url":"https://theskillvault.ai/skills/set-up-env-variables-and-secrets","api_url":"https://theskillvault.ai/api/skills/set-up-env-variables-and-secrets","raw_url":"https://theskillvault.ai/api/skills/set-up-env-variables-and-secrets/raw","body":"# Set up env variables and secrets\n\nKeys and passwords live outside your code. Your code reads them from the environment, and each place it runs gets its own values.\n\n## When to use\n- You have an API key and do not know where to put it.\n- A deploy works locally but not on the host because values are missing.\n- You think you committed a key, or a scanner warned you.\n\n## Steps\n1. Create `.env.local` (or `.env`) for local values and add `.env*` to `.gitignore`, keeping `!.env.example`.\n2. Commit `.env.example` with every variable name and a fake value, so others know what to set.\n3. Read values in code with `process.env.NAME` (or your language's equivalent) and fail early with a clear message if one is missing.\n4. Keep secrets server-side. Only values meant for the browser get a public prefix such as `NEXT_PUBLIC_` or `VITE_`.\n5. Add the values on your host (Vercel, Netlify, Cloudflare, Railway) for each environment: development, preview and production.\n6. Use separate keys for test and live, such as Stripe test keys in preview.\n7. Redeploy after changing values. Most hosts only read them at build or start.\n8. If a secret leaked, rotate it at the provider first, then remove it from the code. Deleting the commit is not enough.\n9. Add a secret scanner (gitleaks or GitHub secret scanning) so it does not happen again.\n\n```bash\n# .env.example\nDATABASE_URL=postgres://user:password@localhost:5432/app\nSTRIPE_SECRET_KEY=sk_test_replace_me\nNEXT_PUBLIC_SITE_URL=http://localhost:3000\n```\n\n## Gotchas\n- Anything with a public prefix is visible to every visitor. Never put secret keys there.\n- Never paste real keys into chats, issues, screenshots or AI prompts.\n- A key in git history stays readable even after you delete the file. Rotate it.\n- Values with spaces or `#` may need quotes in `.env` files.\n\n## Portability\nWorks with any framework and host. If you use a secrets manager (Doppler, 1Password, AWS Secrets Manager) instead of `.env` files, the same split of local, preview and production applies.\n\n## Example prompt\n\"Where should I put my OpenAI and Stripe keys in my Next.js app, and how do I add them on Vercel without leaking them?\"\n\n## Done when\n- No real secret is tracked by git, and `.env.example` lists every variable.\n- Each host environment has its own values and the app starts without missing-variable errors.\n- Any leaked key has been rotated.\n\n---\nHouse original by TheSkillVault (CC-BY-4.0).","files":[],"license":"CC-BY-4.0","license_name":"CC BY 4.0","license_url":"https://creativecommons.org/licenses/by/4.0/","attribution":"From TheSkillVault, https://theskillvault.ai, CC BY 4.0","install":{"claude_code":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-env-variables-and-secrets/raw' -o ~/'.claude/skills/set-up-env-variables-and-secrets/SKILL.md'","cursor":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-env-variables-and-secrets/raw' -o '.cursor/skills/set-up-env-variables-and-secrets/SKILL.md'","agents":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/set-up-env-variables-and-secrets/raw' -o '.agents/skills/set-up-env-variables-and-secrets/SKILL.md'","mcp_url":"https://theskillvault.ai/mcp","cursor_mcp_deeplink":"cursor://anysphere.cursor-deeplink/mcp/install?name=theskillvault&config=eyJ1cmwiOiJodHRwczovL3RoZXNraWxsdmF1bHQuYWkvbWNwIn0%3D","mcp_config":{"mcpServers":{"theskillvault":{"url":"https://theskillvault.ai/mcp"}}}},"bundles":[],"tested_on":[{"family":"chatgpt","name":"ChatGPT","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"claude","name":"Claude","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"gemini","name":"Gemini","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"grok","name":"Grok","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"llama","name":"Llama","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"deepseek","name":"DeepSeek","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"mistral","name":"Mistral","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"qwen","name":"Qwen","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"kimi","name":"Kimi K","outcome":null,"date":null,"source":null,"counts":false,"stale":false}],"proven_rule":{"threshold":5,"window_days":365,"computed_at":"2026-11-02T03:20:33.817Z"}}