Express REST API
Minimal Express 5 JSON API with CORS, a health check and in-memory CRUD routes; uses Node's built-in --watch.
7 steps
Shown with defaults: npm, pip, Node LTS, Python 3.12 and the template's default add-ons.
1. Install and select Node.js with nvm
runtimenvm lets you install several Node.js versions side by side and switch per project. `nvm use` activates it for this shell.
bashnvm install --ltsnvm use --lts- Expected result
- `node -v` prints the selected version.
- Verify
- node -v && npm -v
- OS notes
- macOS/Linux/WSL: install nvm with `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash`, then reopen the terminal. Windows: use nvm-windows (github.com/coreybutler/nvm-windows) from an elevated terminal, or fnm.
2. Create the project folder
templateCreate an empty folder for the project and move into it. All following commands run inside it.
bashmkdir nvx-apicd nvx-api- Expected result
- You are inside ./nvx-api
- Verify
- pwd
3. Initialise package.json
templateCreate a package.json with default values so you can add dependencies and scripts.
bashnpm init -y- Expected result
- A package.json file exists.
- Verify
- node -e "console.log(require('./package.json').name)"
4. Install Express and CORS
templateexpress handles routing; cors lets browsers on other origins call the API.
bashnpm install express cors- Expected result
- express and cors in dependencies.
- Verify
- npm ls express
5. Configure ES modules and scripts
templatenpm pkg set edits package.json safely: enable import syntax and add dev/start scripts (node --watch restarts on save).
bashnpm pkg set type=module 'scripts.dev=node --watch src/index.js' 'scripts.start=node src/index.js'- Expected result
- package.json has "type": "module" and dev/start scripts.
- Verify
- npm pkg get type scripts
6. Write the API server
templateRoutes: GET /health, and CRUD on /api/todos.
Files written by this step: src/index.js
src/index.jsimport express from "express"; import cors from "cors"; export const app = express(); app.use(cors()); app.use(express.json()); let nextId = 1; const todos = []; app.get("/health", (_req, res) => res.json({ ok: true, service: "nvx-api" })); app.get("/api/todos", (_req, res) => res.json(todos)); app.post("/api/todos", (req, res) => { const title = String(req.body?.title ?? "").trim(); if (!title) return res.status(400).json({ error: "title is required" }); const todo = { id: nextId++, title, done: false }; todos.push(todo); res.status(201).json(todo); }); app.patch("/api/todos/:id", (req, res) => { const todo = todos.find((t) => t.id === Number(req.params.id)); if (!todo) return res.status(404).json({ error: "not found" }); if (typeof req.body?.done === "boolean") todo.done = req.body.done; res.json(todo); }); app.delete("/api/todos/:id", (req, res) => { const index = todos.findIndex((t) => t.id === Number(req.params.id)); if (index === -1) return res.status(404).json({ error: "not found" }); todos.splice(index, 1); res.status(204).end(); }); if (process.env.NODE_ENV !== "test") { const port = Number(process.env.PORT) || 3000; app.listen(port, () => console.log("API ready on http://localhost:" + port)); }- Expected result
- src/index.js exists.
- Verify
- node --check src/index.js
7. Run the API
templaterun manually · dev serverStarts the server on port 3000 and restarts on file changes.
bashnpm run dev- Expected result
- Console prints: API ready on http://localhost:3000
- Verify
- curl http://localhost:3000/health