Skip to content
Laviyx Learn

Try

Node.js and Express Cheat Sheet

Running Node, modules, files and paths, process and events, streams and the event loop, Express routes, middleware and errors, status codes, validation, SQLite, auth, security and testing.

Updated

Run and set up#

Terminal
node app.js                    # run a file
node --watch app.js            # restart on changes
node --env-file=.env app.js    # load environment variables
node --test                    # run tests (node:test)
npm init -y && npm pkg set type=module
npm install express            # dependency
npm install -D supertest       # dev dependency
npm ci --omit=dev              # exact, production-only install

Modules#

JavaScript
// ES modules ("type": "module")
import express from "express";
import { readFile } from "node:fs/promises";
import { greet } from "./utils.js";          // relative imports need the extension
export function add(a, b) { return a + b; }
export default class Cart {}
const here = import.meta.dirname;            // __dirname in CommonJS

// CommonJS
const { greet } = require("./utils.cjs");
module.exports = { add };

Files and paths#

JavaScript
import { appendFile, mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
import path from "node:path";

const text = await readFile("notes.txt", "utf8");
await writeFile("out.json", JSON.stringify(data, null, 2));
await appendFile("app.log", "started\n");
await mkdir("reports/2026", { recursive: true });
const names = await readdir("reports");
await rm("tmp", { recursive: true, force: true });

try { await readFile("missing.json", "utf8"); }
catch (err) { if (err.code !== "ENOENT") throw err; }

path.join("data", "orders.json");            // OS separator
path.basename("a/b/report.pdf");             // "report.pdf"
path.extname("report.pdf");                  // ".pdf"
path.join(import.meta.dirname, "public");    // relative to this file

Process, URLs, events#

JavaScript
process.argv.slice(2);                       // command-line arguments
process.env.PORT ?? "3000";                  // env vars are strings
process.exitCode = 1;                        // fail without cutting off output

const url = new URL("https://example.com/search?q=lamp&page=2");
url.searchParams.get("page");                // "2"

import { EventEmitter, once } from "node:events";
const bus = new EventEmitter();
bus.on("order", (o) => console.log(o.id));
bus.on("error", (err) => console.error(err)); // always handle 'error'
bus.emit("order", { id: 7 });

Streams and the event loop#

JavaScript
import { createReadStream, createWriteStream } from "node:fs";
import { createInterface } from "node:readline";
import { pipeline } from "node:stream/promises";
import { createGzip } from "node:zlib";

for await (const line of createInterface({ input: createReadStream("big.log") })) { /* one line */ }
await pipeline(createReadStream("big.log"), createGzip(), createWriteStream("big.log.gz"));

const [user, orders] = await Promise.all([getUser(), getOrders()]);   // run in parallel

Order: synchronous code → microtasks (promises, process.nextTick) → timers → I/O → setImmediate. Never block the event loop with long synchronous work.

Express essentials#

JavaScript
import express from "express";

const app = express();
app.use(express.json({ limit: "100kb" }));

app.get("/api/items", (req, res) => res.json(items));                 // req.query.page
app.get("/api/items/:id", (req, res) => { /* req.params.id */ });
app.post("/api/items", (req, res) => res.status(201).json(created));  // req.body
app.delete("/api/items/:id", (req, res) => res.sendStatus(204));

const router = express.Router();
router.get("/", list);
app.use("/api/orders", router);

app.use(express.static(path.join(import.meta.dirname, "public")));
app.listen(Number(process.env.PORT ?? 3000));

Express 5 paths: optional "/reports{/:year}", wildcard "/files/*path".

Middleware and errors#

JavaScript
function requireAuth(req, res, next) {
  if (!req.get("authorization")) return res.status(401).json({ error: "Login required" });
  next();
}
app.get("/api/me", requireAuth, handler);

app.use((req, res) => res.status(404).json({ error: "Not found" }));   // after routes
app.use((err, req, res, next) => {                                     // 4 params, last
  const status = err.status ?? 500;
  res.status(status).json({ error: status >= 500 ? "Internal error" : err.message });
});

Express 5 forwards errors thrown in async handlers to the error middleware.

Status codes#

200 OK · 201 Created · 204 No Content · 301/302 Redirect · 400 Bad Request · 401 Unauthenticated · 403 Forbidden · 404 Not Found · 409 Conflict · 413 Payload Too Large · 429 Too Many Requests · 500 Server Error

Validation (Zod)#

JavaScript
import { z } from "zod";

const Product = z.object({
  name: z.string().trim().min(2),
  price: z.number().positive(),
  page: z.coerce.number().int().min(1).default(1),    // query strings → numbers
});
const result = Product.safeParse(req.body);
if (!result.success) return res.status(400).json({ errors: result.error.issues });

SQLite (node:sqlite)#

JavaScript
import { DatabaseSync } from "node:sqlite";

const db = new DatabaseSync("app.db");
db.exec("CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT NOT NULL)");
const { lastInsertRowid } = db.prepare("INSERT INTO notes (text) VALUES (?)").run(text);
db.prepare("SELECT * FROM notes WHERE id = ?").get(id);       // one row or undefined
db.prepare("SELECT * FROM notes WHERE text LIKE :q").all({ q: "%milk%" });
db.exec("BEGIN"); /* ... */ db.exec("COMMIT");                // or ROLLBACK on error

Always use placeholders (?, :name); never build SQL from user input.

Auth and security#

JavaScript
import { randomBytes, scrypt, timingSafeEqual } from "node:crypto";
import jwt from "jsonwebtoken";
import helmet from "helmet";
import cors from "cors";

const token = jwt.sign({ sub: String(user.id), role: user.role }, process.env.JWT_SECRET, { expiresIn: "1h" });
const claims = jwt.verify(token, process.env.JWT_SECRET);    // throws if invalid or expired

app.use(helmet());
app.use(cors({ origin: ["https://shop.example.com"] }));

Hash passwords with scrypt/bcrypt/Argon2 and a salt; rate-limit logins; keep secrets in env vars.

Testing#

JavaScript
import assert from "node:assert/strict";
import { test } from "node:test";
import request from "supertest";

test("creates a note", async () => {
  const res = await request(createApp()).post("/api/notes").send({ text: "Hi" });
  assert.equal(res.status, 201);
});

Production checklist#

  • Read PORT and config from the environment; validate it at start-up.
  • Structured logs, a health endpoint, graceful shutdown on SIGTERM.
  • HTTPS, Helmet, strict CORS, rate limits, validation, parameterised SQL.
  • npm audit, tests in CI, managed database with backups and migrations.

Want the full explanations? Go to the Learn Node.js and Express course →