4 Weeks ยท 5 Days/Week ยท 1โ2 Hours Daily
Open your terminal and run:
node -v npm -v
Both should print version numbers.
node-practiceapp.jsnode app.js
// console.log() prints output to the terminal console.log("Hello Node.js"); // You can log any type of value console.log(42); console.log(true); console.log([1, 2, 3]);
node app.js, you should see Hello Node.js printed in the terminal. If you see an error, make sure Node.js is installed properly.// String: text wrapped in quotes const name = "Hafeez"; // Number: integers or decimals let age = 22; let height = 5.9; // Boolean: true or false only let isDeveloper = true; // null: intentionally empty let middleName = null; // undefined: declared but no value yet let country; console.log(name, age, height, isDeveloper); console.log(typeof name); // "string" console.log(typeof age); // "number" console.log(typeof isDeveloper); // "boolean"
// Traditional function declaration function checkAge(age) { if (age >= 18) { console.log("Adult โ"); } else if (age >= 13) { console.log("Teenager"); } else { console.log("Child"); } } checkAge(20); // Adult โ checkAge(15); // Teenager checkAge(8); // Child // Arrow function (modern syntax) โ same thing, shorter const greet = (name) => { return `Hello, ${name}!`; }; console.log(greet("John")); // Hello, John!
const users = ["John", "Sarah", "Tom", "Priya"]; // Access by index (starts at 0) console.log(users[0]); // John // for loop โ classic way for (let i = 0; i < users.length; i++) { console.log(i + 1, users[i]); } // forEach โ modern, cleaner users.forEach((user, index) => { console.log(`${index + 1}. ${user}`); }); // map โ create a new array by transforming each item const upperUsers = users.map(u => u.toUpperCase()); // filter โ keep only items that match a condition const numbers = [1, 2, 3, 4, 5, 6]; const evens = numbers.filter(n => n % 2 === 0); // [2, 4, 6] // Adding/removing items users.push("Alex"); // add to end users.pop(); // remove from end
new User(), the class creates a fresh object with all the defined properties and methods.
// Plain object const user = { name: "Sarah", age: 25, city: "Bangalore", greet() { console.log(`Hi I'm ${this.name}`); } }; user.greet(); // Class โ blueprint for multiple users class User { constructor(name, age, city) { this.name = name; this.age = age; this.city = city; } introduce() { console.log(`Hi, I'm ${this.name}, ${this.age} years old from ${this.city}`); } } const user1 = new User("John", 25, "Mumbai"); const user2 = new User("Priya", 22, "Delhi"); user1.introduce(); user2.introduce();
// setTimeout simulates a delayed operation (like a DB call) function fetchData(callback) { console.log("Fetching data..."); setTimeout(() => { // This runs after 1 second callback("Data received!"); }, 1000); } fetchData((data) => { console.log(data); // Data received! }); console.log("This runs immediately"); // Prints before callback!
// Creating a promise const fetchUser = new Promise((resolve, reject) => { setTimeout(() => { const success = true; if (success) { resolve({ name: "John", age: 25 }); } else { reject("User not found"); } }, 1000); }); // Using the promise fetchUser .then((user) => { console.log("Got user:", user); return user.name; // chain to next .then() }) .then((name) => { console.log("Name is:", name); }) .catch((err) => { console.log("Error:", err); });
.then(), you write async code that looks synchronous but behaves asynchronously. It's the modern standard โ you'll use this constantly when building APIs.
// Mark the function as async async function getData() { return "Hello from async"; } async function main() { const data = await getData(); // wait for it console.log(data); } main(); // Real-world: fetching from an API async function fetchJoke() { try { const response = await fetch("https://official-joke-api.appspot.com/random_joke"); const joke = await response.json(); console.log(joke.setup); console.log(joke.punchline); } catch (err) { console.log("Failed to fetch:", err.message); } } fetchJoke();
console.log("1 โ Start"); // Runs first setTimeout(() => { console.log("3 โ Timeout"); // Runs last (queued) }, 0); Promise.resolve().then(() => { console.log("2 โ Promise"); // Runs before timeout }); console.log("1 โ End"); // Runs second // Output order: Start โ End โ Promise โ Timeout
http module that lets you create web servers without installing anything extra. The server listens on a port (like 3000) and handles incoming HTTP requests.const http = require("http"); const server = http.createServer((req, res) => { // Set response headers res.setHeader("Content-Type", "application/json"); // Route handling if (req.url === "/") { res.statusCode = 200; res.end(JSON.stringify({ message: "Welcome to my server!" })); } else if (req.url === "/users") { res.statusCode = 200; res.end(JSON.stringify([ { name: "John" }, { name: "Sarah" } ])); } else { res.statusCode = 404; res.end(JSON.stringify({ error: "Route not found" })); } }); server.listen(3000, () => { console.log("Server running on http://localhost:3000"); });
Build a Node.js HTTP server from scratch using only the built-in http module โ no Express yet. This reinforces everything from Week 2.
# Create a new project mkdir my-api && cd my-api npm init -y # creates package.json npm install express # installs express
const express = require("express"); const app = express(); // Middleware to parse JSON request bodies app.use(express.json()); // GET route โ home app.get("/", (req, res) => { res.json({ message: "Hello from Express!" }); }); // Start the server app.listen(3000, () => { console.log("Server started on port 3000"); });
/users/:id let you capture dynamic values from the URL.
// Route parameter โ :id is dynamic app.get("/users/:id", (req, res) => { const id = req.params.id; // e.g. /users/42 โ "42" res.json({ message: `Getting user ${id}` }); }); // Query string โ /search?name=john&city=mumbai app.get("/search", (req, res) => { const { name, city } = req.query; res.json({ name, city }); }); // POST โ receive data in req.body app.post("/users", (req, res) => { const { name, email } = req.body; res.status(201).json({ message: "User created", user: { name, email } }); });
req, res, and next. Call next() to continue to the next middleware or route.
// Built-in middleware app.use(express.json()); // parse JSON bodies // Custom middleware โ logger const logger = (req, res, next) => { console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); next(); // must call next or request hangs }; app.use(logger); // Auth middleware โ blocks unauthorized requests const requireAuth = (req, res, next) => { const token = req.headers["authorization"]; if (!token) { return res.status(401).json({ error: "Unauthorized" }); } next(); // token exists, continue }; // Apply auth middleware to a specific route app.get("/dashboard", requireAuth, (req, res) => { res.json({ message: "Welcome to dashboard" }); });
let users = []; // temporary in-memory store let nextId = 1; // CREATE โ POST /users app.post("/users", (req, res) => { const user = { id: nextId++, ...req.body }; users.push(user); res.status(201).json(user); }); // READ ALL โ GET /users app.get("/users", (req, res) => { res.json(users); }); // READ ONE โ GET /users/:id app.get("/users/:id", (req, res) => { const user = users.find(u => u.id === Number(req.params.id)); if (!user) return res.status(404).json({ error: "Not found" }); res.json(user); }); // UPDATE โ PUT /users/:id app.put("/users/:id", (req, res) => { const index = users.findIndex(u => u.id === Number(req.params.id)); if (index === -1) return res.status(404).json({ error: "Not found" }); users[index] = { ...users[index], ...req.body }; res.json(users[index]); }); // DELETE โ DELETE /users/:id app.delete("/users/:id", (req, res) => { users = users.filter(u => u.id !== Number(req.params.id)); res.json({ message: "Deleted successfully" }); });
// Async route with try/catch app.post("/users", async (req, res, next) => { try { const { name, email } = req.body; // Basic validation if (!name || !email) { return res.status(400).json({ error: "Name and email required" }); } // ... create user logic res.status(201).json({ message: "Created" }); } catch (err) { next(err); // pass to error middleware } }); // Global error handler โ must have 4 params app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: "Something went wrong", message: err.message }); }); // 404 handler โ add AFTER all routes app.use((req, res) => { res.status(404).json({ error: "Route not found" }); });
Build a complete REST API for managing users using Express. Data stays in memory for now โ but the API structure should be production-quality.
# Install mongoose
npm install mongoose
const mongoose = require("mongoose"); const connectDB = async () => { try { await mongoose.connect("mongodb://127.0.0.1:27017/myapp"); console.log("MongoDB connected โ"); } catch (err) { console.log("Connection failed:", err.message); process.exit(1); // stop the server if DB fails } }; module.exports = connectDB; // In your index.js, call it: // const connectDB = require("./db"); // connectDB();
const mongoose = require("mongoose"); const userSchema = new mongoose.Schema({ name: { type: String, required: [true, "Name is required"], trim: true }, email: { type: String, required: [true, "Email is required"], unique: true, lowercase: true }, age: { type: Number, min: 0, max: 120 }, role: { type: String, enum: ["user", "admin"], default: "user" } }, { timestamps: true }); // adds createdAt, updatedAt const User = mongoose.model("User", userSchema); module.exports = User;
const User = require("../models/User"); // CREATE app.post("/users", async (req, res) => { try { const user = await User.create(req.body); res.status(201).json(user); } catch (err) { res.status(400).json({ error: err.message }); } }); // READ ALL app.get("/users", async (req, res) => { const users = await User.find().sort({ createdAt: -1 }); res.json(users); }); // UPDATE app.put("/users/:id", async (req, res) => { const user = await User.findByIdAndUpdate( req.params.id, req.body, { new: true, runValidators: true } ); if (!user) return res.status(404).json({ error: "Not found" }); res.json(user); }); // DELETE app.delete("/users/:id", async (req, res) => { await User.findByIdAndDelete(req.params.id); res.json({ message: "Deleted" }); });
const bcrypt = require("bcrypt"); const jwt = require("jsonwebtoken"); const JWT_SECRET = "your-secret-key-change-this"; // REGISTER app.post("/register", async (req, res) => { const { name, email, password } = req.body; const hashedPassword = await bcrypt.hash(password, 10); const user = await User.create({ name, email, password: hashedPassword }); res.status(201).json({ message: "Registered successfully" }); }); // LOGIN app.post("/login", async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) return res.status(401).json({ error: "Invalid credentials" }); const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) return res.status(401).json({ error: "Invalid credentials" }); const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: "7d" }); res.json({ token }); }); // AUTH MIDDLEWARE const protect = (req, res, next) => { const token = req.headers.authorization?.split(" ")[1]; // "Bearer TOKEN" if (!token) return res.status(401).json({ error: "No token" }); try { req.user = jwt.verify(token, JWT_SECRET); next(); } catch { res.status(401).json({ error: "Invalid token" }); } }; // PROTECTED ROUTE app.get("/me", protect, async (req, res) => { const user = await User.findById(req.user.userId).select("-password"); res.json(user); });
my-api/ โโโ models/ โ โโโ User.js โโโ routes/ โ โโโ auth.js โ โโโ users.js โโโ middleware/ โ โโโ protect.js โโโ db.js โโโ .env # secrets (never commit) โโโ .gitignore # add .env and node_modules โโโ index.js # entry point
# .env file
JWT_SECRET=supersecretkey123
MONGODB_URI=mongodb://127.0.0.1:27017/myapp
PORT=3000
npm install dotenv // At the very top of index.js: require("dotenv").config(); // Then use them as: console.log(process.env.JWT_SECRET);
Build a complete authentication system backed by MongoDB. This is the foundation of every real-world application.
Put everything together. Build a production-ready backend system with all the features you've learned.