install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/next-environment-config" ~/.claude/skills/intense-visions-harness-engineering-next-environment-config-cf534f && rm -rf "$T"
manifest:
agents/skills/codex/next-environment-config/SKILL.mdsource content
Next.js Environment Configuration
Manage environment variables, runtime config, and server-only module boundaries safely
When to Use
- Configuring API keys, database URLs, and secrets for server-side code
- Exposing safe configuration values to the browser via
prefixNEXT_PUBLIC_ - Validating environment variables at build time to catch misconfiguration early
- Preventing server-only secrets from leaking into the client bundle
- Configuring different behavior for development, staging, and production environments
Instructions
- Prefix environment variables with
to expose them to the browser — all other variables are server-only.NEXT_PUBLIC_ - Never put secrets (API keys, database URLs, private keys) in
variables — they are inlined into the client bundle.NEXT_PUBLIC_ - Use
ort3-env
to validate environment variables at build time with Zod schemas.@t3-oss/env-nextjs - Create
(orsrc/env.ts
) as the single source of truth for env var access — import env values from here, never fromlib/env.ts
directly in components.process.env - Add
to any module that accesses server-only env vars to prevent accidental client import.import 'server-only' - Use
for local development secrets — it is gitignored by default. Use.env.local
and.env.development
for non-secret environment-specific values..env.production - Wrap
with your env validation so the build fails immediately on missing required variables.next.config.ts - Access runtime environment variables in
vianext.config.ts
— variables set in hosting dashboards (Vercel, Railway) are available at runtime.process.env
// src/env.ts — validated env with t3-env import { createEnv } from '@t3-oss/env-nextjs'; import { z } from 'zod'; export const env = createEnv({ server: { DATABASE_URL: z.string().url(), NEXTAUTH_SECRET: z.string().min(32), STRIPE_SECRET_KEY: z.string().startsWith('sk_'), }, client: { NEXT_PUBLIC_APP_URL: z.string().url(), NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().startsWith('pk_'), }, runtimeEnv: { DATABASE_URL: process.env.DATABASE_URL, NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY, NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, }, }); // lib/db.ts — import 'server-only' prevents client bundle inclusion import 'server-only'; import { env } from '@/env'; import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; const client = postgres(env.DATABASE_URL); export const db = drizzle(client);
Details
Next.js treats environment variables differently depending on when and where they are accessed:
Build-time inlining:
NEXT_PUBLIC_ variables are replaced with their literal values at build time (process.env.NEXT_PUBLIC_API_URL becomes "https://api.example.com" in the bundle). This means the value is fixed at build time and cannot change at runtime without rebuilding.
Server-only variables: Variables without
NEXT_PUBLIC_ are only available in Server Components, Route Handlers, and other server-side code. Accessing them in a Client Component returns undefined and does not leak the value — it simply does not work.
file priority: Next.js loads .env
.env, .env.local, .env.development/.env.production, and .env.development.local/.env.production.local. More specific files override less specific ones. .local files take highest priority and should be in .gitignore.
Runtime vs build-time: Variables set in the Vercel dashboard are available at runtime in server-side code. However,
NEXT_PUBLIC_ variables must be set at build time in Vercel — setting them in the dashboard alone requires a rebuild.
t3-env benefits: Without validation, a missing
DATABASE_URL crashes the app at the first database query — potentially after deployment. t3-env fails the build or server startup immediately with a clear error listing every missing or invalid variable.
package: server-only
import 'server-only' causes a build error if the module is imported in a Client Component. Use it in any module that accesses secrets, database clients, or other server-only resources. Pair with client-only for the inverse — marking browser-only modules.
Source
https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.