Deployment, environments and secrets
Build versus runtime, what belongs in an environment variable, and what a deployment must survive.
15 min read
The track ends with something running at a URL that someone else can open. This is what stands between a repository and that.
Build time and runtime are different places. A value inlined during the build is baked into the JavaScript that every visitor downloads. A value read on a server at runtime is not. Frameworks mark the difference by convention, usually with a prefix such as VITE_ or NEXT_PUBLIC_, and that prefix is a statement: this will be public. Putting a secret behind such a prefix does not protect it, it publishes it.
What belongs in an environment variable. Anything that differs between your machine and the deployed site: the API base URL, the public key of a service, a feature flag. Anything that must remain unknown to visitors belongs on a server, and the browser receives only the result of using it.
Commit an example, never the real file. A .env.example listing the names with empty values tells the next person what is required. The real .env belongs in .gitignore. A secret committed once stays in the history even after it is deleted, so the only real remedy is to rotate it.
A deployment must survive a reload on a sub-page. A single-page application serves one HTML file for every route. If the host is not configured to do that, the home page works and /program/dashboard returns a 404 on refresh. It is one of the most common defects in a first deployment, and it never appears while clicking through locally.
Check the deployed build, not the development server. The development server is more forgiving: it tolerates missing environment variables, serves uncompressed files and hides errors that only appear once the code is minified. Build locally and serve the output at least once before you call it done.
Go deeper
Lessons are not assessed. Progress towards the certificate is recorded from the work you submit. See all requirements