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 |
Recommended VS Code Extensions
| 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 |
nvm use 20. Many projects require specific Node versions, and nvm makes this effortless. On Windows, use nvm-windows instead.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
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 |