Back to blog
nodejsbeginner

Node.js & Express Environment Setup

Install Node.js, scaffold an Express project with TypeScript, understand the module system, and run your first API server in under 20 minutes.

LearnixoApril 16, 20264 min read
Node.jsExpressTypeScriptSetupBeginner
Share:š•

Node.js lets you run JavaScript on the server. Express is the most popular web framework for Node — minimal, unopinionated, and battle-tested. Together they power APIs at companies from small startups to Netflix.


Install Node.js

Use the LTS version. Check at nodejs.org or use a version manager:

Bash
# Using nvm (recommended — lets you switch Node versions)
nvm install --lts
nvm use --lts

# Verify
node --version   # v20.x.x or higher
npm --version    # 10.x.x

Create a Project

Bash
mkdir my-api && cd my-api
npm init -y

Install Express and TypeScript:

Bash
npm install express
npm install -D typescript ts-node-dev @types/node @types/express

Initialize TypeScript:

Bash
npx tsc --init

Update tsconfig.json with sensible defaults:

JSON
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Add scripts to package.json:

JSON
{
  "scripts": {
    "dev": "ts-node-dev --respawn --transpile-only src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

Your First Express Server

src/index.ts

TYPESCRIPT
import express, { Request, Response } from 'express';

const app = express();
const PORT = process.env.PORT ?? 3000;

// Middleware — parse JSON bodies
app.use(express.json());

// Routes
app.get('/', (req: Request, res: Response) => {
  res.json({ message: 'Hello from Express!' });
});

app.get('/health', (req: Request, res: Response) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// Start server
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

Run the dev server:

Bash
npm run dev

Open http://localhost:3000 — you'll see the JSON response.


Project Structure

my-api/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ index.ts              ← entry point
│   ā”œā”€ā”€ app.ts                ← Express app (without listen)
│   ā”œā”€ā”€ routes/
│   │   ā”œā”€ā”€ users.ts
│   │   └── products.ts
│   ā”œā”€ā”€ controllers/
│   │   ā”œā”€ā”€ user.controller.ts
│   │   └── product.controller.ts
│   ā”œā”€ā”€ middleware/
│   │   ā”œā”€ā”€ auth.middleware.ts
│   │   └── error.middleware.ts
│   ā”œā”€ā”€ models/               ← TypeScript interfaces + DB models
│   └── services/             ← business logic
ā”œā”€ā”€ package.json
└── tsconfig.json

Separate app.ts from index.ts — app.ts creates and exports the Express instance, index.ts starts the server. This makes testing easier (import the app without starting a server).

src/app.ts

TYPESCRIPT
import express from 'express';
import { userRouter } from './routes/users';
import { productRouter } from './routes/products';

const app = express();

app.use(express.json());
app.use('/api/users', userRouter);
app.use('/api/products', productRouter);

export { app };

src/index.ts

TYPESCRIPT
import { app } from './app';

const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => console.log(`Server on port ${PORT}`));

Environment Variables

Never hardcode secrets. Use a .env file with dotenv:

Bash
npm install dotenv

.env (never commit this):

PORT=3000
DATABASE_URL=postgres://localhost:5432/mydb
JWT_SECRET=supersecretkey

src/index.ts:

TYPESCRIPT
import 'dotenv/config';   // load .env before anything else
import { app } from './app';

const PORT = process.env.PORT ?? 3000;
app.listen(PORT);

Add .env to .gitignore. Commit a .env.example with empty values so other developers know what's needed.


Node.js Module System

Node uses CommonJS (require/module.exports) by default. TypeScript compiles to CommonJS unless you configure otherwise. You'll also see ES Modules (.mjs or "type": "module" in package.json):

TYPESCRIPT
// TypeScript (compiles to CommonJS)
import express from 'express';
export function add(a: number, b: number): number { return a + b; }

// What Node actually runs (CommonJS):
const express = require('express');
function add(a, b) { return a + b; }
module.exports = { add };

Stick with CommonJS for Node.js + TypeScript unless you have a specific reason to use ES Modules.


Useful Dev Tools

Bash
# REST client for testing APIs
npm install -g httpie
http GET localhost:3000/health

# Or use curl
curl http://localhost:3000/health

# nodemon alternative (built into ts-node-dev)
# ts-node-dev auto-restarts when TypeScript files change

Install the Thunder Client VS Code extension or Postman for a GUI API client.


Quick Reference

Init project:   npm init -y
Install:        npm i express && npm i -D typescript ts-node-dev @types/node @types/express
Dev server:     npm run dev  (ts-node-dev --respawn src/index.ts)
Build:          tsc → dist/
Production:     node dist/index.js
Environment:    dotenv → process.env.VAR_NAME
Split app:      app.ts (express()) vs index.ts (app.listen())

Enjoyed this article?

Explore the learning path for more.

Found this helpful?

Share:š•

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.