Learning Goals
3 minBy the end of this lesson you will be able to:
- Explain why a password or API key must never be typed into your source code.
- Store settings in a
.envfile and load them withrequire('dotenv').config(). - Read a value at runtime with
process.env— for example, your server's port. - Add
.envto.gitignoreso your secrets never reach GitHub.
Warm-Up · Spot the Danger
5 minLast lesson you served JSON and static files. Today's server needs a database password and a payment key. Read this snippet, then spot what is dangerous:
const express = require('express')
const app = express()
const dbPassword = 'nasiLemak123'
const stripeKey = 'sk_live_8f3k9d2p7q'
app.listen(4000)Predict together
- The code runs fine. So what is the problem?
- If Aisyah pushes this file to GitHub, who can now read that password and key?
Reveal
The secrets are written into the source. The moment this file is committed, the password and key live in your Git history forever — even if you delete the lines later. On a public GitHub repo, anyone in the world can read them. Bots scan GitHub for keys within seconds. Secrets must live outside the code. That is what we fix today.
New Concept · The Locked Drawer
12 minImagine your code is a wall everyone can read. You would never paint your house key onto the wall. Instead you keep it in a locked drawer. Your code walks to the drawer and asks for the key — but the key itself is never written on the wall.
That drawer is a .env file. An environment variable is a named setting kept outside your code. Node hands them to you through an object called process.env.
The syntax box
First, the drawer. A .env file is a plain list of NAME=value lines — one per line, no quotes needed:
PORT=4000
API_KEY=sk_live_9h2k4m7p1xNext, your code asks the drawer for its values. One line at the very top loads the file; after that, every value is on process.env:
require('dotenv').config()
const port = process.env.PORT
console.log('Port is', port)dotenv is a small package that reads the .env file and copies each line onto process.env. Call .config() before you read any value.
On the wall (bad)
The secret is typed into the code.
Git saves it forever, for anyone to read.
One file to change means editing code.
In the drawer (good)
The secret lives only in .env.
.env is git-ignored, so it never ships.
Different values for development and for the live server.
Why it matters
Two reasons. Security: keys stay off GitHub, so nobody can steal your database or spend your money. And flexibility: your laptop can use PORT=4000 while the live server uses a different port — same code, different drawer.
Worked Example · Move the Port into .env
12 minWei Jie has an Express server with a hard-coded port. Follow along in your own project folder to move it into a .env file, the safe way.
Step 1 — Install dotenv
In the terminal, inside your project folder, run:
$ npm install dotenvnpm downloads the package and records it:
added 1 package in 1sStep 2 — Create the .env file
Make a new file called .env (the name starts with a dot, and there is nothing before it). Put your settings inside:
PORT=4000
API_KEY=sk_live_9h2k4m7p1xStep 3 — Read it in the server
Add require('dotenv').config() as the very first line, then use process.env.PORT:
require('dotenv').config()
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.get('/', (req, res) => {
res.send('Server is running.')
})
app.listen(port, () => {
console.log('Listening on port ' + port)
})The || 3000 is a fallback: if .env has no PORT, the server still starts on port 3000 instead of crashing.
Step 4 — Ignore .env in Git
Open (or make) a file called .gitignore and add one line so Git never tracks your secrets:
node_modules
.envStep 5 — Run it
Start the server:
$ node server.jsListening on port 4000What changed? The port 4000 is no longer in your code — the server read it from the .env drawer. Change the file to PORT=5000, restart, and the server moves. Your secrets stay off GitHub, and your settings live in one tidy place.
Try It Yourself
13 minWork in the same project. Restart the server after each change with node server.js to see it take effect.
Task 1 — Add a greeting
Add a line
GREETING=Selamat datangto your.env. In a route, read it withprocess.env.GREETINGand send it back:app.get('/hi', (req, res) => { res.send(process.env.GREETING) })Visit
/hiin your browser and check the greeting shows.Task 2 — Move the port
Change
PORTin.envto a new number, for examplePORT=5050. Restart the server. Confirm the terminal now printsListening on port 5050, and visit the new address in your browser.Task 3 — Prove it is ignored
Make sure
.envis listed in.gitignore. Then rungit statusin the terminal. Your.envfile should not appear in the list of files to commit — Git is now ignoring it.
Mini-Challenge · The Welcome Route
8 minBuild a route /welcome that returns a message using a SITE_NAME environment variable. It must combine today's concept with the routing you learned earlier in Section A.
It works if: with SITE_NAME=Advaslearning Hub in .env, visiting /welcome shows Welcome to Advaslearning Hub! — and if you delete that line, it still shows a sensible fallback instead of crashing.
Reveal a sample answer
require('dotenv').config()
const express = require('express')
const app = express()
// Fallback keeps the server working if the var is missing.
const siteName = process.env.SITE_NAME || 'our website'
app.get('/welcome', (req, res) => {
res.send('Welcome to ' + siteName + '!')
})
app.listen(process.env.PORT || 3000)With SITE_NAME=Advaslearning Hub in .env, the browser shows:
Welcome to Advaslearning Hub!Remove that line, restart, and the fallback takes over — Welcome to our website! The || is what stops a missing variable from breaking your server.
Recap
3 min- Never type passwords or API keys into your source code.
- Keep settings in a
.envfile — oneNAME=valueper line. dotenvloads that file: callrequire('dotenv').config()at the very top.- Read any value at runtime with
process.env.NAME, plus a||fallback. - Add
.envto.gitignoreso secrets never reach GitHub.
New words
- Environment variable — a named setting kept outside your code.
- process.env — the object Node uses to hand you those settings.
- dotenv — a package that loads a
.envfile intoprocess.env. - .env — the file that holds your settings and secrets.
- .gitignore — a list of files Git must never track or upload.
Homework
4 min to brief · ~20 min to doRequired
- In one of your Express projects, move the port and one secret (any fake key will do) into a
.envfile. Load it withdotenvand read both withprocess.env. - Add
.envto.gitignore. Rungit statusand take a screenshot showing that.envis not listed. Bring it to next lesson.
Optional stretch
- Write a short paragraph: why is committing secrets to GitHub so dangerous, even on a private repo you later make public?
- Search for the term secret scanner. In one or two sentences, explain what it does and why GitHub runs one on every push.