Complete Node.js Course

Master Server-Side JavaScript Development

1. Introduction to Node.js

Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It allows you to run JavaScript on the server side, enabling full-stack JavaScript development.

What is Node.js?

Why Node.js?

Node.js Use Cases

Perfect for:

  • Web APIs: RESTful services and GraphQL
  • Real-time Apps: Chat applications, live updates
  • Microservices: Lightweight, scalable services
  • Command Line Tools: Build automation, utilities
  • IoT Applications: Handle sensor data and device communication
💡 Tip: Node.js is not suitable for CPU-intensive tasks due to its single-threaded nature. It excels at I/O-intensive applications.

2. Setting Up Node.js

Installation

# Download from nodejs.org or use package managers # macOS (using Homebrew) brew install node # Ubuntu/Debian sudo apt update sudo apt install nodejs npm # Windows (using Chocolatey) choco install nodejs # Verify installation node --version npm --version

Node Version Manager (NVM)

# Install NVM (Linux/macOS) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash # Install and use specific Node version nvm install 18.17.0 nvm use 18.17.0 nvm alias default 18.17.0 # List installed versions nvm list

Your First Node.js Program

// hello.js console.log("Hello, Node.js!"); console.log("Current directory:", __dirname); console.log("Current file:", __filename); console.log("Node version:", process.version); console.log("Platform:", process.platform);
# Run the program node hello.js

Try Node.js:

Click to see Node.js in action!

3. Node.js Basics

Global Objects

// Global objects available in Node.js console.log("Global object:", global); console.log("Process object:", process.pid); console.log("Current working directory:", process.cwd()); console.log("Environment variables:", process.env.NODE_ENV); // Timers setTimeout(() => { console.log("This runs after 2 seconds"); }, 2000); setInterval(() => { console.log("This runs every 3 seconds"); }, 3000); // Buffer for binary data const buffer = Buffer.from("Hello World", "utf8"); console.log("Buffer:", buffer); console.log("Buffer to string:", buffer.toString());

Process Object

// Command line arguments console.log("Arguments:", process.argv); // Environment variables console.log("NODE_ENV:", process.env.NODE_ENV || "development"); console.log("PORT:", process.env.PORT || 3000); // Process events process.on("exit", (code) => { console.log(`Process exiting with code: ${code}`); }); process.on("uncaughtException", (error) => { console.error("Uncaught Exception:", error); process.exit(1); }); // Exit the process // process.exit(0);

Event Loop and Asynchronous Programming

// Synchronous vs Asynchronous console.log("Start"); // Asynchronous - goes to callback queue setTimeout(() => { console.log("Timeout callback"); }, 0); // Asynchronous - goes to microtask queue (higher priority) Promise.resolve().then(() => { console.log("Promise resolved"); }); // Synchronous console.log("End"); // Output order: Start, End, Promise resolved, Timeout callback
⚠️ Important: Understanding the event loop is crucial for Node.js development. Microtasks (Promises) have higher priority than macrotasks (setTimeout, setInterval).

4. Modules and Require

CommonJS Modules

// math.js - Creating a module function add(a, b) { return a + b; } function subtract(a, b) { return a - b; } function multiply(a, b) { return a * b; } // Export functions module.exports = { add, subtract, multiply }; // Alternative export syntax // exports.add = add; // exports.subtract = subtract;
// app.js - Using the module const math = require('./math'); // or destructuring const { add, subtract } = require('./math'); console.log("5 + 3 =", math.add(5, 3)); console.log("10 - 4 =", subtract(10, 4)); // Built-in modules const path = require('path'); const os = require('os'); console.log("File extension:", path.extname('file.txt')); console.log("Operating System:", os.platform()); console.log("Free memory:", os.freemem());

ES6 Modules (ESM)

// package.json - Enable ES modules { "type": "module" } // math.mjs - ES6 module export function add(a, b) { return a + b; } export function subtract(a, b) { return a - b; } export default function multiply(a, b) { return a * b; } // app.mjs - Using ES6 modules import multiply, { add, subtract } from './math.mjs'; import path from 'path'; console.log("5 + 3 =", add(5, 3)); console.log("5 * 3 =", multiply(5, 3));

Core Modules

// Path module const path = require('path'); console.log("Join paths:", path.join('/users', 'john', 'documents')); console.log("Resolve path:", path.resolve('file.txt')); console.log("Parse path:", path.parse('/users/john/file.txt')); // OS module const os = require('os'); console.log("Platform:", os.platform()); console.log("Architecture:", os.arch()); console.log("CPU count:", os.cpus().length); console.log("Total memory:", os.totalmem()); console.log("Home directory:", os.homedir()); // URL module const url = require('url'); const myUrl = new URL('https://example.com:8080/path?name=john&age=30'); console.log("Protocol:", myUrl.protocol); console.log("Host:", myUrl.host); console.log("Pathname:", myUrl.pathname); console.log("Search params:", myUrl.searchParams.get('name'));

🏋️ Exercise 1:

Create a module that exports functions to calculate the area and perimeter of different shapes (circle, rectangle, triangle).

5. NPM (Node Package Manager)

Package.json

// Initialize a new project npm init npm init -y // Skip questions // package.json structure { "name": "my-node-app", "version": "1.0.0", "description": "My awesome Node.js application", "main": "index.js", "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "jest" }, "keywords": ["node", "javascript"], "author": "Your Name", "license": "MIT", "dependencies": { "express": "^4.18.2", "lodash": "^4.17.21" }, "devDependencies": { "nodemon": "^3.0.1", "jest": "^29.5.0" } }

Installing Packages

# Install packages npm install express # Production dependency npm install -D nodemon # Development dependency npm install -g nodemon # Global installation # Install specific version npm install express@4.18.2 # Install from package.json npm install # Update packages npm update npm outdated # Remove packages npm uninstall express npm uninstall -D nodemon

Popular NPM Packages

Essential Packages:

  • express: Web framework
  • lodash: Utility library
  • axios: HTTP client
  • moment: Date manipulation
  • mongoose: MongoDB ODM
  • bcrypt: Password hashing
  • jsonwebtoken: JWT tokens
  • dotenv: Environment variables
  • cors: Cross-origin resource sharing
  • helmet: Security middleware

Using NPM Packages

// Install: npm install lodash axios const _ = require('lodash'); const axios = require('axios'); // Using lodash const numbers = [1, 2, 3, 4, 5]; const doubled = _.map(numbers, n => n * 2); console.log("Doubled:", doubled); const users = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }, { name: 'Bob', age: 35 } ]; const sortedUsers = _.sortBy(users, 'age'); console.log("Sorted by age:", sortedUsers); // Using axios for HTTP requests async function fetchData() { try { const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1'); console.log("Post title:", response.data.title); } catch (error) { console.error("Error fetching data:", error.message); } } fetchData();

NPM Scripts

// package.json scripts { "scripts": { "start": "node server.js", "dev": "nodemon server.js", "test": "jest", "build": "webpack --mode production", "lint": "eslint .", "format": "prettier --write ." } }
# Run scripts npm start npm run dev npm test npm run build

6. File System Operations

Reading and Writing Files

const fs = require('fs'); const path = require('path'); // Synchronous file operations try { // Write file fs.writeFileSync('example.txt', 'Hello, Node.js!'); console.log('File written successfully'); // Read file const data = fs.readFileSync('example.txt', 'utf8'); console.log('File content:', data); // Check if file exists if (fs.existsSync('example.txt')) { console.log('File exists'); } } catch (error) { console.error('Error:', error.message); } // Asynchronous file operations (recommended) fs.writeFile('async-example.txt', 'Hello, Async!', (err) => { if (err) { console.error('Error writing file:', err); return; } console.log('Async file written'); fs.readFile('async-example.txt', 'utf8', (err, data) => { if (err) { console.error('Error reading file:', err); return; } console.log('Async file content:', data); }); });

Promises and Async/Await with Files

const fs = require('fs').promises; async function fileOperations() { try { // Write file await fs.writeFile('promise-example.txt', 'Hello, Promises!'); console.log('Promise file written'); // Read file const data = await fs.readFile('promise-example.txt', 'utf8'); console.log('Promise file content:', data); // Get file stats const stats = await fs.stat('promise-example.txt'); console.log('File size:', stats.size, 'bytes'); console.log('Created:', stats.birthtime); console.log('Modified:', stats.mtime); // Append to file await fs.appendFile('promise-example.txt', '\nAppended text'); // Read updated content const updatedData = await fs.readFile('promise-example.txt', 'utf8'); console.log('Updated content:', updatedData); } catch (error) { console.error('Error:', error.message); } } fileOperations();

Working with Directories

const fs = require('fs').promises; const path = require('path'); async function directoryOperations() { try { // Create directory await fs.mkdir('test-dir', { recursive: true }); console.log('Directory created'); // Read directory contents const files = await fs.readdir('.'); console.log('Current directory files:', files); // Create nested directories await fs.mkdir('nested/deep/directory', { recursive: true }); // Copy file await fs.copyFile('example.txt', 'test-dir/copied-file.txt'); // Rename/move file await fs.rename('test-dir/copied-file.txt', 'test-dir/renamed-file.txt'); // Delete file await fs.unlink('test-dir/renamed-file.txt'); // Remove directory await fs.rmdir('test-dir'); } catch (error) { console.error('Directory operation error:', error.message); } } directoryOperations();

Streams for Large Files

const fs = require('fs'); const path = require('path'); // Reading large files with streams function readLargeFile(filename) { const readStream = fs.createReadStream(filename, { encoding: 'utf8' }); readStream.on('data', (chunk) => { console.log('Received chunk of size:', chunk.length); // Process chunk }); readStream.on('end', () => { console.log('Finished reading file'); }); readStream.on('error', (error) => { console.error('Stream error:', error.message); }); } // Writing with streams function writeWithStream(filename, data) { const writeStream = fs.createWriteStream(filename); writeStream.write(data); writeStream.end(); writeStream.on('finish', () => { console.log('Finished writing file'); }); writeStream.on('error', (error) => { console.error('Write stream error:', error.message); }); } // Pipe streams (copy file) function copyFileWithStreams(source, destination) { const readStream = fs.createReadStream(source); const writeStream = fs.createWriteStream(destination); readStream.pipe(writeStream); readStream.on('end', () => { console.log('File copied successfully'); }); }

7. HTTP Module

Creating a Basic HTTP Server

const http = require('http'); const url = require('url'); // Create server const server = http.createServer((req, res) => { // Parse URL const parsedUrl = url.parse(req.url, true); const path = parsedUrl.pathname; const method = req.method; // Set response headers res.setHeader('Content-Type', 'text/html'); res.setHeader('Access-Control-Allow-Origin', '*'); // Route handling if (path === '/' && method === 'GET') { res.statusCode = 200; res.end('

Welcome to Node.js Server!

'); } else if (path === '/about' && method === 'GET') { res.statusCode = 200; res.end('

About Page

This is a Node.js server

'); } else if (path === '/api/users' && method === 'GET') { res.setHeader('Content-Type', 'application/json'); res.statusCode = 200; const users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' } ]; res.end(JSON.stringify(users)); } else { res.statusCode = 404; res.end('

404 - Page Not Found

'); } }); // Start server const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });

Handling POST Requests

const http = require('http'); const url = require('url'); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); const path = parsedUrl.pathname; const method = req.method; if (path === '/api/users' && method === 'POST') { let body = ''; // Collect data chunks req.on('data', (chunk) => { body += chunk.toString(); }); // Process complete data req.on('end', () => { try { const userData = JSON.parse(body); console.log('Received user data:', userData); // Simulate saving user const newUser = { id: Date.now(), ...userData, createdAt: new Date().toISOString() }; res.setHeader('Content-Type', 'application/json'); res.statusCode = 201; res.end(JSON.stringify({ message: 'User created successfully', user: newUser })); } catch (error) { res.statusCode = 400; res.end(JSON.stringify({ error: 'Invalid JSON' })); } }); } else { res.statusCode = 404; res.end(JSON.stringify({ error: 'Route not found' })); } }); server.listen(3000, () => { console.log('Server running on port 3000'); });

Making HTTP Requests

const http = require('http'); const https = require('https'); // GET request function makeGetRequest(url) { const client = url.startsWith('https') ? https : http; client.get(url, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { console.log('Response:', JSON.parse(data)); }); }).on('error', (error) => { console.error('Request error:', error.message); }); } // POST request function makePostRequest(hostname, path, postData) { const options = { hostname: hostname, port: 443, path: path, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) } }; const req = https.request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { console.log('POST Response:', data); }); }); req.on('error', (error) => { console.error('POST Request error:', error.message); }); req.write(postData); req.end(); } // Usage makeGetRequest('https://jsonplaceholder.typicode.com/posts/1'); const postData = JSON.stringify({ title: 'My Post', body: 'This is my post content', userId: 1 }); makePostRequest('jsonplaceholder.typicode.com', '/posts', postData);

8. Express.js Framework

Getting Started with Express

# Install Express npm install express npm install -D nodemon
const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware app.use(express.json()); // Parse JSON bodies app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies // Basic routes app.get('/', (req, res) => { res.send('

Welcome to Express!

'); }); app.get('/api/users', (req, res) => { const users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' } ]; res.json(users); }); app.get('/api/users/:id', (req, res) => { const userId = parseInt(req.params.id); const user = { id: userId, name: 'John Doe', email: 'john@example.com' }; res.json(user); }); app.post('/api/users', (req, res) => { const { name, email } = req.body; const newUser = { id: Date.now(), name, email, createdAt: new Date().toISOString() }; res.status(201).json(newUser); }); app.listen(PORT, () => { console.log(`Express server running on port ${PORT}`); });

Express Middleware

const express = require('express'); const app = express(); // Built-in middleware app.use(express.json()); app.use(express.static('public')); // Serve static files // Custom middleware app.use((req, res, next) => { console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`); next(); // Call next middleware }); // Authentication middleware const authenticateToken = (req, res, next) => { const token = req.headers['authorization']; if (!token) { return res.status(401).json({ error: 'Access token required' }); } // Verify token (simplified) if (token === 'Bearer valid-token') { req.user = { id: 1, name: 'John Doe' }; next(); } else { res.status(403).json({ error: 'Invalid token' }); } }; // Error handling middleware app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: 'Something went wrong!' }); }); // Protected route app.get('/api/protected', authenticateToken, (req, res) => { res.json({ message: 'This is protected data', user: req.user }); }); // 404 handler (should be last) app.use('*', (req, res) => { res.status(404).json({ error: 'Route not found' }); });

Express Router

// routes/users.js const express = require('express'); const router = express.Router(); let users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' } ]; // GET /api/users router.get('/', (req, res) => { res.json(users); }); // GET /api/users/:id router.get('/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); }); // POST /api/users router.post('/', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).json({ error: 'Name and email are required' }); } const newUser = { id: users.length + 1, name, email }; users.push(newUser); res.status(201).json(newUser); }); // PUT /api/users/:id router.put('/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'User not found' }); } const { name, email } = req.body; if (name) user.name = name; if (email) user.email = email; res.json(user); }); // DELETE /api/users/:id router.delete('/:id', (req, res) => { const userIndex = users.findIndex(u => u.id === parseInt(req.params.id)); if (userIndex === -1) { return res.status(404).json({ error: 'User not found' }); } users.splice(userIndex, 1); res.status(204).send(); }); module.exports = router; // app.js const express = require('express'); const userRoutes = require('./routes/users'); const app = express(); app.use(express.json()); app.use('/api/users', userRoutes); app.listen(3000, () => { console.log('Server running on port 3000'); });

🏋️ Exercise 2:

Create an Express API for a simple blog with routes for creating, reading, updating, and deleting blog posts. Include middleware for logging and error handling.

9. Database Integration

MongoDB with Mongoose

# Install MongoDB and Mongoose npm install mongoose
const mongoose = require('mongoose'); // Connect to MongoDB mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true, useUnifiedTopology: true }); // Define schema const userSchema = new mongoose.Schema({ name: { type: String, required: true, trim: true }, email: { type: String, required: true, unique: true, lowercase: true }, age: { type: Number, min: 0, max: 120 }, createdAt: { type: Date, default: Date.now } }); // Create model const User = mongoose.model('User', userSchema); // CRUD operations async function userOperations() { try { // Create user const newUser = new User({ name: 'John Doe', email: 'john@example.com', age: 30 }); await newUser.save(); console.log('User created:', newUser); // Find users const users = await User.find(); console.log('All users:', users); // Find one user const user = await User.findOne({ email: 'john@example.com' }); console.log('Found user:', user); // Update user const updatedUser = await User.findByIdAndUpdate( user._id, { age: 31 }, { new: true } ); console.log('Updated user:', updatedUser); // Delete user await User.findByIdAndDelete(user._id); console.log('User deleted'); } catch (error) { console.error('Database error:', error.message); } } userOperations();

Express + MongoDB API

const express = require('express'); const mongoose = require('mongoose'); const app = express(); app.use(express.json()); // Connect to MongoDB mongoose.connect('mongodb://localhost:27017/blog'); // Blog post schema const postSchema = new mongoose.Schema({ title: { type: String, required: true }, content: { type: String, required: true }, author: { type: String, required: true }, tags: [String], createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now } }); const Post = mongoose.model('Post', postSchema); // Routes app.get('/api/posts', async (req, res) => { try { const posts = await Post.find().sort({ createdAt: -1 }); res.json(posts); } catch (error) { res.status(500).json({ error: error.message }); } }); app.get('/api/posts/:id', async (req, res) => { try { const post = await Post.findById(req.params.id); if (!post) { return res.status(404).json({ error: 'Post not found' }); } res.json(post); } catch (error) { res.status(500).json({ error: error.message }); } }); app.post('/api/posts', async (req, res) => { try { const post = new Post(req.body); await post.save(); res.status(201).json(post); } catch (error) { res.status(400).json({ error: error.message }); } }); app.put('/api/posts/:id', async (req, res) => { try { const post = await Post.findByIdAndUpdate( req.params.id, { ...req.body, updatedAt: new Date() }, { new: true, runValidators: true } ); if (!post) { return res.status(404).json({ error: 'Post not found' }); } res.json(post); } catch (error) { res.status(400).json({ error: error.message }); } }); app.delete('/api/posts/:id', async (req, res) => { try { const post = await Post.findByIdAndDelete(req.params.id); if (!post) { return res.status(404).json({ error: 'Post not found' }); } res.status(204).send(); } catch (error) { res.status(500).json({ error: error.message }); } }); app.listen(3000, () => { console.log('Blog API running on port 3000'); });

Environment Variables

// Install dotenv // npm install dotenv // .env file NODE_ENV=development PORT=3000 MONGODB_URI=mongodb://localhost:27017/myapp JWT_SECRET=your-secret-key API_KEY=your-api-key // app.js require('dotenv').config(); const express = require('express'); const mongoose = require('mongoose'); const app = express(); // Use environment variables const PORT = process.env.PORT || 3000; const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/defaultdb'; mongoose.connect(MONGODB_URI); app.get('/', (req, res) => { res.json({ environment: process.env.NODE_ENV, port: PORT, message: 'Environment variables loaded!' }); }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });

10. Practice Projects

Project 1: RESTful API with Authentication

const express = require('express'); const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); require('dotenv').config(); const app = express(); app.use(express.json()); // User schema const userSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, createdAt: { type: Date, default: Date.now } }); // Hash password before saving userSchema.pre('save', async function(next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 10); next(); }); const User = mongoose.model('User', userSchema); // Middleware to verify JWT const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (!token) { return res.status(401).json({ error: 'Access token required' }); } jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(403).json({ error: 'Invalid token' }); } req.user = user; next(); }); }; // Register route app.post('/api/register', async (req, res) => { try { const { username, email, password } = req.body; // Check if user exists const existingUser = await User.findOne({ $or: [{ email }, { username }] }); if (existingUser) { return res.status(400).json({ error: 'User already exists' }); } // Create user const user = new User({ username, email, password }); await user.save(); // Generate token const token = jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET, { expiresIn: '24h' } ); res.status(201).json({ message: 'User registered successfully', token, user: { id: user._id, username: user.username, email: user.email } }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Login route app.post('/api/login', async (req, res) => { try { const { email, password } = req.body; // Find user const user = await User.findOne({ email }); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } // Check password const isValidPassword = await bcrypt.compare(password, user.password); if (!isValidPassword) { return res.status(401).json({ error: 'Invalid credentials' }); } // Generate token const token = jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET, { expiresIn: '24h' } ); res.json({ message: 'Login successful', token, user: { id: user._id, username: user.username, email: user.email } }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Protected route app.get('/api/profile', authenticateToken, async (req, res) => { try { const user = await User.findById(req.user.userId).select('-password'); res.json(user); } catch (error) { res.status(500).json({ error: error.message }); } }); mongoose.connect(process.env.MONGODB_URI); app.listen(process.env.PORT, () => { console.log(`Auth API running on port ${process.env.PORT}`); });

Project 2: Real-time Chat Application

// Install: npm install socket.io const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const path = require('path'); const app = express(); const server = http.createServer(app); const io = socketIo(server); // Serve static files app.use(express.static('public')); // Store connected users const users = new Map(); // Socket.io connection handling io.on('connection', (socket) => { console.log('User connected:', socket.id); // Handle user joining socket.on('join', (username) => { users.set(socket.id, username); socket.broadcast.emit('user-joined', username); // Send current users list io.emit('users-list', Array.from(users.values())); }); // Handle messages socket.on('message', (data) => { const username = users.get(socket.id); const messageData = { username, message: data.message, timestamp: new Date().toISOString() }; // Broadcast message to all clients io.emit('message', messageData); }); // Handle typing indicator socket.on('typing', () => { const username = users.get(socket.id); socket.broadcast.emit('typing', username); }); socket.on('stop-typing', () => { socket.broadcast.emit('stop-typing'); }); // Handle disconnection socket.on('disconnect', () => { const username = users.get(socket.id); users.delete(socket.id); if (username) { socket.broadcast.emit('user-left', username); io.emit('users-list', Array.from(users.values())); } console.log('User disconnected:', socket.id); }); }); const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Chat server running on port ${PORT}`); }); // public/index.html (basic chat interface) /* Node.js Chat
*/

🏋️ Project Ideas:

Build these projects to master Node.js:

  • Task Management API: CRUD operations with user authentication
  • File Upload Service: Handle file uploads with multer
  • URL Shortener: Create short URLs like bit.ly
  • Weather API: Fetch and cache weather data
  • Blog Platform: Full-featured blog with comments
  • E-commerce API: Products, orders, and payments
  • Real-time Notifications: WebSocket-based notifications
  • GraphQL API: Modern API with GraphQL

Next Steps

Advanced Node.js Topics:

  • Testing: Jest, Mocha, Supertest
  • Security: Helmet, rate limiting, input validation
  • Performance: Clustering, caching, optimization
  • Deployment: Docker, PM2, cloud platforms
  • Microservices: Service architecture patterns
  • GraphQL: Apollo Server, schema design
  • TypeScript: Type-safe Node.js development
  • Monitoring: Logging, metrics, error tracking