Why passwords, tokens and settings belong outside your source code: how environment variables and a .env file work, the .env.example convention, and how to make a program fail gracefully when a setting is missing.
The same program runs in at least two places: on your laptop while you build it, and on a server for everyone else. The two need different settings: a test password here, a real one there; a local port here, a port chosen by the host there. If those values are typed into the code, you must edit the code to move between places, and a password typed into code ends up in your history for good. The fix is a rule that is simple to say: settings live outside the code.
What an environment variable is, how a .env file and a .env.example file work together, which settings are secrets and which are not, and how to make a program behave sensibly when a setting is missing.
Your code asks for a setting by name, and whoever runs the program supplies the value. In Node.js that looks like this:
const port = process.env.PORT || 8080;
The code says "use the PORT setting if there is one, otherwise 8080." On a laptop there is no PORT, so it uses 8080. On a hosting platform that sets PORT, the same line picks up the platform's value. The code did not change; only the surroundings did.
Most projects use a pair of files:
.env holds the real values, one NAME=value per line. It exists only on your machine and is never committed. This site's .gitignore lists it, and also blocks anything shaped like .env.*..env.example holds the same names with the values left blank, plus comments explaining each one. This one is committed, and .gitignore has an explicit exception for it.Anyone who clones the project copies .env.example to .env, fills in their own values, and the program runs. The example file is the documentation of what the program needs.
Look at the kinds of settings a real small website needs. This site's example file lists:
The first four are secrets: whoever holds them can act as you. The bucket name is just a setting. Treat the two groups differently: secrets must never be committed, while ordinary settings are safe to keep in the code as defaults. A committed secret stays in every copy of the repository and in its history, and deleting the line later does not un-publish it.
Every setting can be missing, so decide in advance what happens.
const token = process.env.API_TOKEN;
if (!token) console.warn('API_TOKEN is not set: the data card will be skipped');
The example file contains a note about the shared secret for scheduled jobs: send it in a request header, not in the web address, because addresses end up in access logs, browser history and Referer headers. Where you put a secret matters as much as whether it is hidden. For more on keeping secrets out of the wrong places, read Secrets Management: Don't Commit Passwords.
Limits and switches are good candidates for environment variables too. The AI tutor described in Guardrails for an AI Feature keeps its message limits and its monthly spending ceiling as settings, so changing a limit does not mean touching code.
Take any small project of yours and: (1) list every value that differs between your laptop and a server; (2) mark each one "secret" or "ordinary"; (3) create a .env.example with the names and no values; (4) run git check-ignore -v .env and confirm Git reports a rule for it, so the real file cannot be committed by mistake; (5) change one line of code to read a setting from process.env with a sensible default.
To see how the built program and its settings reach a live server, read From git push to a Running Container on Cloud Run.
Practical credential hygiene for real projects — why secrets don't belong in source control, how .gitignore and environment variables actually protect you (and where they don't), and what to do if a secret is committed by mistake.
A line-by-line walkthrough of a real Dockerfile and Cloud Build file: what a container image is, how the four build steps work, why images are tagged with the commit, and what Cloud Run does with the result.
How to put an AI model behind safe limits: why most of the protection is ordinary code around the model, how rate limits, a monthly budget ceiling and anonymous logs work, and the real bugs found before launch.