Build a production-shaped app

Protect environment values

Keep server configuration outside source control and understand exactly when a value becomes part of browser-visible code.

8 minute lesson

~~~

Next.js loads environment files for local work. Values without the NEXT_PUBLIC_ prefix remain server-only when used in server code.

A public prefix deliberately inlines a value into browser code at build time, so it must never hold a secret. The public value is frozen when the app is built: promoting the same artifact to another environment does not replace it at runtime.

Keep .env.local ignored, provide a documented .env.example with names but no values, and configure real values in the deployment platform. Validate required configuration near the server entry point rather than failing deep inside a request.

// lib/server/config.ts
import 'server-only'

const notesApiToken = process.env.NOTES_API_TOKEN
if (!notesApiToken) throw new Error('NOTES_API_TOKEN is required')

export const serverConfig = { notesApiToken }

server-only turns an accidental Client Component import into a build error. It is a guardrail, not a vault. A value still leaks if server code renders it into HTML, passes it as a client prop, includes it in an error, or logs it somewhere other people can read.

Add NOTES_API_TOKEN through the guarded config module and its empty name to .env.example. Deliberately import the module from a Client Component to observe the failure, then remove the import. Inspect Git, HTML, client props, built JavaScript, and production logs for the token value.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →