env-and-secrets

Enforce environment variable access through zod-validated modules and ESLint gating in Next.js projects.

Updated Jan 12, 2026
One-click install
npx skills add https://github.com/brandonarbini/arbini.family --skill env-and-secrets-brandonarbini
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: env-and-secrets
Source: https://github.com/brandonarbini/arbini.family/tree/main/.agents/skills/env-and-secrets
Command: npx skills add https://github.com/brandonarbini/arbini.family --skill env-and-secrets-brandonarbini

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill requires zod.

What problem does it solve? Environment variables in Next.js projects often fail silently: a missing variable surfaces as undefined deep in a page render, secrets get committed accidentally, and .gitignore rules for .env files break in subtle order-dependent ways. This Skill defines the policy for which env files are tracked, how variables are read through validated modules, and where secrets actually live per environment. ## Core Features & Use Cases - Validated env access: All process.env reads go through lib/env/server.ts or lib/env/client.ts, which parse a zod 4 schema at import so missing variables fail loudly at boot. - ESLint gate: eslint.dev-env.mjs restricts direct process.env access via no-restricted-properties, spread as the last element of the flat config so it cannot be silently overridden. - Gitignore policy: Defines which .env files are tracked (.env, .env.example, .env.test) versus ignored (.env.local, .env.production), verifiable with git check-ignore -v. - Secret placement guidance: Directs credentials to devcontainer .env.local, GitHub Actions secrets, or Vercel project variables, and pnpm env:cloud prints the block a cloud environment still needs. - Use Case: When adding a new API key, edit the zod schema in lib/env/server.ts, add a placeholder to .env.example, and import it — the build then fails up front if the variable is missing anywhere. ## Quick Start Add a new environment variable to this Next.js project following the env-and-secrets conventions and tell me where its secret value should live in each environment.

Frequently Asked Questions about env-and-secrets

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I add a new environment variable in a Next.js project?▼

Add the variable to the zod schema in lib/env/server.ts (or lib/env/client.ts for NEXT_PUBLIC_* values), add a placeholder to .env.example, then import it from that module. Editing the schema rather than the call site makes missing variables fail at boot.

How do I restrict direct process.env access with ESLint?▼

Use the no-restricted-properties rule rather than the deprecated no-process-env, since it also catches process.env["X"] and destructuring. Spread the dev-env config as the last element of your flat ESLint config so later project entries cannot override it.

Should .env be gitignored in a Next.js repository?▼

In this setup, bare .env stays tracked because it carries non-secret development defaults that devcontainers, CI, and cloud VMs read on bootstrap. Only .env.local, .env.production, and .env.development.local are ignored; verify behavior with git check-ignore -v.

Why does next build fail on a missing environment variable?▼

Because next.config.ts imports ./lib/env/server, whose zod schema parses at import time and throws on any missing required variable. This makes the build fail up front instead of a page render failing deep into the build.

Where should secrets be stored for CI and Vercel deployments?▼

Secrets never go in the repository. Use gitignored .devcontainer/.env.local for devcontainers, GitHub Actions secrets referenced from workflow files for CI, and Vercel project environment variables set in the dashboard for deployments.

Why must NEXT_PUBLIC variables be read as static members?▼

Next.js inlines NEXT_PUBLIC_* values at build time, which only works when they are read as static member accesses. They belong exclusively in lib/env/client.ts and must never be mixed into the server-only module.