Configuration decides how the same code behaves in development, staging, and production. Secrets are sensitive configuration values that must never ship to browsers or source control.
Public vs Private
Frontend public config can include values like API base paths and analytics ids. Backend private config includes database URLs, signing keys, and provider tokens.
Your app has two kinds of configuration: things that are fine for anyone to see (like an API URL) and things that are secret (like a database password). Mixing these up is a real security risk in a full-stack app.
Public vs. private
Public config — safe to ship in your frontend bundle (an API base URL, an analytics ID). Anyone can see it in DevTools anyway.
Private secrets — must stay on the server only: database URLs, signing keys, third-party tokens.
Anything that ends up in your frontend’s JavaScript bundle is visible to everyone, no matter how it’s named. Never put real secrets there — only truly public values.
Fail loudly if something’s missing
Don’t let your app start with broken configuration — check for required values immediately and refuse to boot if any are missing:
function requireEnv(name) { const value = process.env[name] if (!value) throw new Error(`Missing environment variable ${name}`) return value}const databaseUrl = requireEnv('DATABASE_URL')
A clear “missing config” crash at startup is far better than a confusing failure deep inside a request later.
In one sentence
Split configuration into public (safe for the frontend bundle) and private secrets (server-only, never shipped to browsers), and validate all required values at startup so missing config fails fast and clearly.
Want to go deeper?
Switch to Expert mode above for credential rotation and documenting environment setup for a team.