Setting Up the Development Environment

โ–ถ Try It Yourself

A consistent, well-configured development environment is the foundation of a productive MEAN Stack workflow. Before you write a single line of application code, you need four things installed and verified: Node.js (which includes npm), MongoDB (locally or via Atlas), the Angular CLI, and a code editor configured for TypeScript and JavaScript. In this lesson you will install and verify every tool, understand what each one provides, create your first Angular project and Express server side by side, and confirm that all four layers of the stack can run together on your machine.

Required Tools

Tool Version What It Provides Install Via
Node.js 20 LTS JavaScript runtime + npm package manager nodejs.org or nvm
npm Included with Node Package installation and script running Bundled with Node
MongoDB Community 7.x Local database server mongodb.com/try/download
MongoDB Compass Latest GUI to browse and query MongoDB mongodb.com/products/compass
Angular CLI 17+ Scaffold, build, serve Angular apps npm install -g @angular/cli
VS Code Latest Editor with TypeScript and Angular support code.visualstudio.com
Postman or Insomnia Latest Test REST API endpoints manually postman.com
Extension Publisher Purpose
Angular Language Service Angular Autocomplete and type checking in Angular templates
ESLint Microsoft JavaScript and TypeScript linting
Prettier Prettier Auto-format on save
MongoDB for VS Code MongoDB Browse collections inside the editor
Thunder Client Ranga Vadhineni Lightweight REST client inside VS Code
GitLens GitKraken Enhanced Git history and blame
Note: Always install Node.js via nvm (Node Version Manager) rather than the installer from nodejs.org โ€” especially on macOS and Linux. nvm lets you switch between Node versions per project with a simple nvm use 20. Many projects require specific Node versions, and nvm makes this effortless. On Windows, use nvm-windows instead.
Tip: If you prefer not to install MongoDB locally, use MongoDB Atlas โ€” the free cloud-hosted tier (M0) is more than enough for development and learning. Sign up at cloud.mongodb.com, create a free cluster, and get a connection string. This also mirrors the production setup you would use when deploying your application.
Warning: Do not install the Angular CLI with sudo npm install -g on macOS/Linux โ€” this creates permission issues. If you installed Node via nvm, global npm packages install into your home directory automatically without needing sudo. If you get permission errors, fix npm’s global directory rather than using sudo.

Step-by-Step Installation

# โ”€โ”€ Step 1: Install nvm (macOS / Linux) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Restart your terminal, then:
nvm install 20        # install Node 20 LTS
nvm use 20            # activate it
nvm alias default 20  # make it the default

# On Windows โ€” install nvm-windows from:
# https://github.com/coreybutler/nvm-windows/releases

# โ”€โ”€ Step 2: Verify Node and npm โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
node --version    # should print v20.x.x
npm --version     # should print 10.x.x

# โ”€โ”€ Step 3: Install Angular CLI globally โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
npm install -g @angular/cli
ng version        # verify โ€” should print Angular CLI: 17.x.x

# โ”€โ”€ Step 4: Install MongoDB (macOS via Homebrew) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
brew tap mongodb/brew
brew install mongodb-community@7.0
brew services start mongodb-community@7.0

# On Ubuntu:
# Follow: https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/

# On Windows:
# Download MSI from mongodb.com/try/download/community
# Install as a Windows Service

# โ”€โ”€ Step 5: Verify MongoDB โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
mongosh           # opens MongoDB shell
# Type: db.runCommand({ ping: 1 })
# Should print: { ok: 1 }
# Type: exit to quit

# โ”€โ”€ Step 6: Install Postman โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Download from: https://www.postman.com/downloads/

Project Scaffold

# โ”€โ”€ Create the project root โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
mkdir task-manager
cd task-manager

# โ”€โ”€ Create the Angular frontend โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ng new frontend   --routing=true   --style=scss   --skip-tests=false
# Answer: CSS or SCSS โ†’ choose SCSS
# Answer: Server-Side Rendering โ†’ No (for now)

# โ”€โ”€ Create the Express backend โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
mkdir backend
cd backend
npm init -y    # creates package.json

# Install core backend dependencies
npm install express mongoose dotenv cors helmet bcryptjs jsonwebtoken
npm install express-validator multer

# Install development dependencies
npm install -D nodemon eslint

# โ”€โ”€ Final project structure โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
task-manager/
โ”œโ”€โ”€ frontend/              โ† Angular app (ng serve โ†’ port 4200)
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”œโ”€โ”€ assets/
โ”‚   โ”‚   โ””โ”€โ”€ environments/
โ”‚   โ”œโ”€โ”€ angular.json
โ”‚   โ””โ”€โ”€ package.json
โ”‚
โ””โ”€โ”€ backend/               โ† Express API (nodemon โ†’ port 3000)
    โ”œโ”€โ”€ src/
    โ”‚   โ”œโ”€โ”€ controllers/
    โ”‚   โ”œโ”€โ”€ models/
    โ”‚   โ”œโ”€โ”€ routes/
    โ”‚   โ”œโ”€โ”€ middleware/
    โ”‚   โ””โ”€โ”€ config/
    โ”œโ”€โ”€ .env
    โ””โ”€โ”€ package.json

Hello World โ€” Verify Every Layer

// backend/src/index.js โ€” minimal Express server
const express = require('express');
const cors    = require('cors');
require('dotenv').config();

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

app.use(cors({ origin: 'http://localhost:4200' }));
app.use(express.json());

// Health check endpoint
app.get('/api/health', (req, res) => {
    res.json({
        status:    'ok',
        message:   'MEAN Stack API is running',
        timestamp: new Date().toISOString(),
        stack: {
            node:    process.version,
            express: require('express/package.json').version,
        }
    });
});

app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});
# backend/.env
PORT=3000
MONGODB_URI=mongodb://localhost:27017/taskmanager
JWT_SECRET=your_super_secret_key_change_in_production
NODE_ENV=development

# Run the backend
cd backend
node src/index.js
# โ†’ Server running on http://localhost:3000

# Test it
curl http://localhost:3000/api/health
# โ†’ { "status": "ok", "message": "MEAN Stack API is running" }
# Run the Angular frontend
cd frontend
ng serve
# โ†’ Application bundle generation complete.
# โ†’ Local: http://localhost:4200/

# Open browser โ†’ http://localhost:4200
# โ†’ Angular default homepage confirms frontend is running
// frontend/src/app/app.component.ts โ€” call the backend health endpoint
import { Component, OnInit } from '@angular/core';
import { HttpClient }        from '@angular/common/http';

@Component({
    selector:    'app-root',
    template:    `
        <h1>MEAN Stack โ€” Task Manager</h1>
        <p>API Status: {{ apiStatus }}</p>
    `,
})
export class AppComponent implements OnInit {
    apiStatus = 'Checking...';

    constructor(private http: HttpClient) {}

    ngOnInit() {
        this.http.get<any>('http://localhost:3000/api/health').subscribe({
            next:  res  => this.apiStatus = res.status,
            error: _err => this.apiStatus = 'Cannot reach API',
        });
    }
}

How It Works

Step 1 โ€” Node.js Runs Your Express Server

When you run node src/index.js, Node.js starts and executes the file. Express registers route handlers and begins listening on the specified port. From this point, Node’s event loop waits for incoming HTTP connections. It processes one request at a time conceptually, but its non-blocking I/O lets it handle thousands of concurrent requests efficiently while waiting for database responses.

Step 2 โ€” Angular CLI Starts a Dev Server

ng serve starts a Webpack (or Vite) development server that compiles your TypeScript and Angular templates, bundles them, and serves them on port 4200. It watches for file changes and hot-reloads the browser automatically. The Angular app in the browser makes HTTP requests to port 3000 (the Express API) โ€” these are two entirely separate processes communicating over HTTP.

Step 3 โ€” CORS Allows Cross-Origin Requests

The browser blocks JavaScript from making requests to a different origin (domain + port) by default. Since Angular runs on port 4200 and Express on port 3000, they are different origins. The cors middleware in Express sends the correct Access-Control-Allow-Origin headers, telling the browser to permit these cross-origin requests from http://localhost:4200.

Step 4 โ€” dotenv Loads Environment Variables

require('dotenv').config() reads your .env file and loads each key-value pair as process.env.KEY. This keeps sensitive values (database passwords, JWT secrets) out of your source code. The .env file is added to .gitignore โ€” it never gets committed. In production, environment variables are set directly on the server or in a secrets manager.

Step 5 โ€” nodemon Restarts on File Changes

Instead of stopping and restarting Node manually after every code change, nodemon watches your backend files and restarts the server automatically. Add a dev script to package.json: "dev": "nodemon src/index.js". Running npm run dev gives you the same hot-reload experience on the backend that ng serve gives you on the frontend.

Real-World Example: package.json Scripts

// backend/package.json
{
  "name": "task-manager-api",
  "version": "1.0.0",
  "scripts": {
    "start":  "node src/index.js",
    "dev":    "nodemon src/index.js",
    "lint":   "eslint src/**/*.js",
    "test":   "jest --runInBand"
  },
  "dependencies": {
    "bcryptjs":         "^2.4.3",
    "cors":             "^2.8.5",
    "dotenv":           "^16.4.1",
    "express":          "^4.18.2",
    "express-validator":"^7.0.1",
    "helmet":           "^7.1.0",
    "jsonwebtoken":     "^9.0.2",
    "mongoose":         "^8.1.0",
    "multer":           "^1.4.5"
  },
  "devDependencies": {
    "eslint":   "^8.56.0",
    "jest":     "^29.7.0",
    "nodemon":  "^3.0.3",
    "supertest":"^6.3.4"
  }
}
// Root package.json โ€” run both servers with one command
{
  "name": "task-manager",
  "scripts": {
    "frontend": "cd frontend && ng serve",
    "backend":  "cd backend && npm run dev",
    "dev":      "npm run backend & npm run frontend"
  },
  "devDependencies": {
    "concurrently": "^8.2.2"
  }
}

Common Mistakes

Mistake 1 โ€” Committing the .env file to Git

โŒ Wrong โ€” sensitive credentials exposed in version control:

git add .env   # NEVER do this
git commit -m "add config"
# Your database password is now in public Git history

โœ… Correct โ€” always add .env to .gitignore before the first commit:

echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
# Create .env.example with placeholder values for teammates
echo "PORT=3000
MONGODB_URI=
JWT_SECRET=" > .env.example
git add .env.example .gitignore

Mistake 2 โ€” CORS not configured โ€” Angular cannot reach Express

โŒ Wrong โ€” no CORS middleware, browser blocks requests:

const app = express();
// Missing cors() โ€” browser will block all requests from port 4200
app.get('/api/tasks', handler);

โœ… Correct โ€” add CORS before all routes:

const cors = require('cors');
app.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:4200' }));

Mistake 3 โ€” Running npm install in the wrong folder

โŒ Wrong โ€” installing Express inside the Angular project:

cd task-manager/frontend   # wrong folder!
npm install express        # Express installed inside Angular โ€” wastes space and confuses bundler

โœ… Correct โ€” each project has its own node_modules:

cd task-manager/backend    # backend dependencies go here
npm install express mongoose

cd task-manager/frontend   # frontend dependencies go here
npm install @angular/material

▶ Try It Yourself

Quick Reference โ€” Useful Commands

Command What It Does
nvm install 20 Install Node.js 20 LTS
npm install -g @angular/cli Install Angular CLI globally
ng new my-app --routing --style=scss Scaffold new Angular project
ng serve Start Angular dev server on port 4200
npm run dev Start Express with nodemon (auto-restart)
mongosh Open MongoDB shell
node --version Verify Node installation
ng version Verify Angular CLI version

🧠 Test Yourself

Why must CORS be configured on the Express server when Angular calls it from the browser?





โ–ถ Try It Yourself