# Node js - day3

### What is Node.js?

Node.js is a **runtime environment** that allows you to run JavaScript outside of the browser, on a server. Imagine you’re writing JavaScript code that isn’t for a webpage but for the server, where the backend logic runs.

Here’s a simple analogy:

* Think of JavaScript as a tool (like a pen).
    
* Browsers (like Chrome or Firefox) are like paper where you usually use the tool.
    
* Node.js is like a whiteboard where you can use the same tool (JavaScript) in a different way to do backend tasks.
    

It was built using **V8**, the engine that powers Google Chrome, which is responsible for running JavaScript super fast.

---

### Why Do We Need Node.js for Backend Development?

In web development, there are two main sides:

1. **Frontend**: What the user sees (handled by HTML, CSS, and JavaScript).
    
2. **Backend**: What happens behind the scenes, like handling data, user authentication, and serving requests.
    

Node.js is used on the **backend** to:

1. **Handle Web Requests and Responses**
    
    * Example: A user clicks “Login” on a website. The backend (using Node.js) will check the credentials and respond with success or error.
        
2. **Run JavaScript on the Server**
    
    * Traditionally, JavaScript was only used on the frontend. Node.js allows you to use it on the backend too, so you can use one language for both sides.
        
3. **Build Fast and Scalable Applications**
    
    * Node.js can handle many requests at the same time without slowing down, making it perfect for real-time apps like chat systems or online gaming.
        
4. **Use NPM (Node Package Manager)**
    
    * NPM gives you access to thousands of pre-built tools and libraries to speed up development (e.g., authentication, database connections, etc.).
        

---

### Why Node.js is Popular for Backend Development?

1. **Fast**:
    
    * Its event-driven, non-blocking nature means it doesn’t wait for one task to finish before starting another.  
        Example: While waiting for a file to download, Node.js can handle another request simultaneously.
        
2. **Easy to Learn**:
    
    * If you know JavaScript for frontend, you can quickly pick up Node.js for backend.
        
3. **Real-Time Applications**:
    
    * Perfect for apps like messaging, notifications, or live updates because it handles multiple connections simultaneously.
        
4. **Cross-Platform**:
    
    * Works on Windows, macOS, and Linux, so developers can build and deploy anywhere.
        
5. **Large Community**:
    
    * Many developers use Node.js, meaning tons of resources, tutorials, and solutions are available.
        

---

---

### Why Choose Node.js Over Other Backend Technologies?

* **Speed**: It's great for real-time, high-traffic applications.
    
* **Single Language**: You can use JavaScript for both the frontend and backend.
    
* **Scalability**: Perfect for apps that need to handle a growing number of users.
    

---

### **1\. How to Initialize a Node.js Project**

To initiate a Node.js project, you’ll use `npm` (Node Package Manager), which is bundled with Node.js. The `npm init` command helps you set up the `package.json` file, which contains metadata about your project (like the project’s name, version, description, and dependencies).

#### **Steps to Initialize a Node.js Project**

1. **Step 1: Install Node.js**
    
    Before starting, ensure that Node.js is installed on the system. If it’s not installed, direct your students to [the official Node.js website](https://nodejs.org/) to download and install the latest LTS version.
    
    After installing, confirm by running:
    
    ```c
    node -v
    ```
    
    This command should return the installed Node.js version. You can also check npm:
    
    ```c
    npm -v
    ```
    
2. **Step 2: Create a Project Folder**
    
    Let’s say you want to create a new project called `my_project`. Start by creating a new folder for your project:
    
    ```c
    mkdir my_project
    cd my_project
    ```
    
3. **Step 3: Initialize the Node.js Project**
    
    In the `my_project` directory, run:
    
    ```c
    npm init
    ```
    
    * This command will guide you through a series of prompts to fill out the details of your project:
        
        * **name**: The name of your project (default is the folder name).
            
        * **version**: The version of your project (default is `1.0.0`).
            
        * **description**: A short description of your project.
            
        * **entry point**: The main file for your project (default is `index.js`).
            
        * **test command**: The command to run tests (you can leave this blank for now).
            
        * **git repository**: If your project has a Git repository, you can provide the URL.
            
        * **keywords**: Words that describe your project.
            
        * **author**: Your name.
            
        * **license**: The license for your project (default is `ISC`).
            
    
    You can skip any question by pressing `Enter` to accept the default.
    
4. **Step 4: Creating the** `package.json`
    
    After answering all the prompts, `npm` will create a `package.json` file in your project directory. This file will look like this:
    
    ```c
    {
      "name": "my_project",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    ```
    
    * `name`: The name of the project.
        
    * `version`: The version of your project.
        
    * `description`: The project description.
        
    * `main`: The entry point file (default is `index.js`).
        
    * `scripts`: Defines npm scripts (e.g., `npm test` can run tests).
        

---

### **2\. Running Your First Node.js Script**

Now that you've initialized your project, you can write some basic code to test it out.

1. **Create the** `index.js` file: In the `my_project` folder, create a file named `index.js`:
    
    ```c
    
    
    console.log("Hello, Node.js!");
    ```
    
2. **Run the script**: In the terminal, run the following command:
    
    ```c
    node index.js
    ```
    
    This should output:
    
    ```c
    Hello, Node.js!
    ```
    

---

### **. Understanding** `package.json` and `node_modules`

* `package.json`: This file tracks metadata about the project, including dependencies, scripts, and more.
    
* `node_modules/`: This folder contains all the installed dependencies for your project. It's created automatically when you install packages via `npm`.
    

**Note:** The `node_modules` folder and the `package-lock.json` file should generally not be committed to version control (e.g., Git). You can add `node_modules/` to your `.gitignore` file.

### **Common npm Commands**

Here are some common `npm` commands your students should be familiar with:

* `npm init`: Initializes a new Node.js project and creates a `package.json` file.
    
* `npm install <package-name>`: Installs a package and adds it to the `node_modules` folder.
    
* `npm install`: Installs all the dependencies listed in the `package.json` file.
    
* `npm uninstall <package-name>`: Removes a package from the project.
    
* `npm run <script-name>`: Runs a script defined in the `package.json` file (e.g., `npm run start`).
    

### **Summary for Students**

* `npm init`: Initializes a new Node.js project and creates a `package.json` file.
    
* `node index.js`: Runs your Node.js application.
    
* `npm install <package-name>`: Installs a third-party package.
    
* `package.json`: Contains project metadata, dependencies, and scripts.
    
* `node_modules/`: Folder containing installed packages.
    

### **Understanding** `module.exports` in Node.js

Now that your students have learned how to initiate a Node.js project and run basic scripts, it's time to introduce them to the concept of modules in Node.js. Modules allow you to break down your application into smaller, manageable pieces of code, making your application easier to organize and scale.

In Node.js, the `module.exports` object is the mechanism used to expose functionality from a module to be used in other parts of your application.

#### **What is** `module.exports`?

* In Node.js, each file is treated as a module.
    
* The `module.exports` object allows you to export functions, objects, variables, or even entire modules from one file, so they can be used in other files.
    

#### **Basic Syntax for** `module.exports`

You can assign functions, objects, or values to `module.exports` to make them available outside the module.

* **Export a Function:**
    
* ```c
      // add.js
      
      function add(a, b) {
          return a + b;
      }
      
      module.exports = add;  // Exporting the add function
    ```
    
    Importing the Function in Another File:
    
* ```c
      // main.js
      
      const add = require('./add');  // Importing the add function
      
      console.log(add(2, 3));  // Outputs: 5
    ```
    
    #### **Explanation:**
    
    * In the `add.js` file, the function `add` is assigned to `module.exports`.
        
    * In `main.js`, we use `require('./add')` to import the `add` function and then call it.
        
    
    #### **Exporting Multiple Functions or Objects**
    
    Instead of exporting just one function, you can export multiple functions or variables from a single file.
    
    * **Export Multiple Functions:**
        
        ```c
        
        
        function add(a, b) {
            return a + b;
        }
        
        function subtract(a, b) {
            return a - b;
        }
        
        module.exports = {
            add: add,
            subtract: subtract
        };
        ```
        
    * **Importing Multiple Functions:**
        
        ```c
        
        
        const math = require('./math');  // Importing the math module
        
        console.log(math.add(5, 3));     // Outputs: 8
        console.log(math.subtract(5, 3));  // Outputs: 2
        ```
        
    
    #### **Explanation:**
    
    * In `math.js`, we export an object with two properties: `add` and `subtract`.
        
    * In `main.js`, we import the entire `math` object and use its functions.
        
    
    ---
    
    #### **Best Practices for Using** `module.exports`:
    
    * **Encapsulation:** Only export the functionality you need. Don’t expose everything in your module.
        
    * **Keep it Simple:** If you have only one function or class to export, use `module.exports = functionName` for simplicity.
        
    * **Organize Code:** Group related functions or classes into their own modules to keep your project organized and easy to maintain.
        
    
    ### **Project Structure**
    
    ```c
    simple_calculator/
    ├── index.js            // Main entry point
    ├── operations/         
    │   └── mathOperations.js  // Contains add and subtract functions
    ```
    
    ### **Step 1: Creating the** `mathOperations.js` file
    
    This file will contain the basic math functions: **add** and **subtract**.
    
    ```c
    
    
    function add(a, b) {
        return a + b;
    }
    
    function subtract(a, b) {
        return a - b;
    }
    
    // Exporting the functions so they can be used in other files
    module.exports = { add, subtract };
    ```
    
    #### Explanation:
    
    * The `add` function takes two numbers (`a` and `b`) and returns their sum.
        
    * The `subtract` function takes two numbers (`a` and `b`) and returns their difference.
        
    * We use `module.exports` to export both functions so they can be accessed from other files.
        
    
    ### **Step 2: Creating the** `index.js` file
    
    This file is the main entry point of the application. It will import the functions from `mathOperations.js` and use them.
    
    ```c
    
    
    const mathOperations = require('./operations/mathOperations');  // Importing the math functions
    
    // Using the add function
    const resultAdd = mathOperations.add(5, 3);
    console.log('Addition Result: ', resultAdd);  // Output: 8
    
    // Using the subtract function
    const resultSubtract = mathOperations.subtract(5, 3);
    console.log('Subtraction Result: ', resultSubtract);  // Output: 2
    ```
    
    #### Explanation:
    
    * In `index.js`, we use `require('./operations/mathOperations')` to import the `add` and `subtract` functions from the `mathOperations.js` file located in the `operations` folder.
        
    * We then call the `add` function with the numbers `5` and `3` and print the result.
        
    * Similarly, we call the `subtract` function and print the result.
        
    
    ### **Step 3: How to Run the Code**
    
    1. **Run the Application**: Open your terminal, navigate to the project directory, and run `index.js` with Node.js:
        
        ```c
        node index.js
        ```
        
    2. **Expected Output**: After running the code, you should see the following output in the terminal:
        
        ```c
        Addition Result:  8
        Subtraction Result:  2
        ```
        
    
    ---
    
    ### **Step 4: Navigating with** `./` and `../`
    
    * `./` (Current Directory):
        
        * In `index.js`, we used `require('./operations/mathOperations')` to reference the `mathOperations.js` file from the **current directory**. The `./` means "look in the current directory for the `operations` folder."
            
    * `../` (Parent Directory):
        
        * If `index.js` was located inside another folder (like a `src` folder), we would have to use `../` to go up one level and then access `operations/mathOperations.js`. For example: `require('../operations/mathOperations')`.
            
    
    ---
    
    ### **Summary for Students:**
    
    1. `module.exports`:
        
        * This allows you to **export functions** from a file so that they can be used in other files.
            
        * In this case, we exported the `add` and `subtract` functions from `mathOperations.js` to be used in `index.js`.
            
    2. **Navigating the File System**:
        
        * `./` is used to refer to the **current directory**. You use it when the file you want to access is in the same directory.
            
        * `../` is used to go **up one level** to the parent directory. You use it when you need to reference files that are located in a folder above the current directory.
            
    
    By using this simple example, students will be able to understand how to:
    
    * Structure a basic Node.js project with multiple files.
        
    * Export and import functions using `module.exports` and `require()`.
        
    * Navigate the file system using relative paths like `./` and `../`.
        
    
    ### **Introduction to Express**
    
    Express is a minimal and flexible Node.js web application framework that provides a robust set of features for building web and mobile applications. It simplifies many aspects of building web servers, such as handling requests, responses, and routing, all while being lightweight.
    
    #### **What does Express do?**
    
    * Express allows you to build web applications and APIs quickly and efficiently.
        
    * It simplifies handling HTTP requests (like GET, POST, PUT, DELETE).
        
    * It provides a way to manage middleware for logging, authentication, error handling, etc.
        
    
    ---
    
    ### **2\. Setting up Express**
    
    Before diving into routing, let's walk through how to set up an Express application:
    
    1. **Install Express**: You need to install Express in your Node.js project. If you haven't initialized a Node project yet, first run:
        
        ```c
        npm init -y
        ```
        
        Then, install Express:
        
        ```c
        npm install express
        ```
        
    2. **Creating the Basic Express App**: In your `index.js` file, you can set up a simple Express server as follows:
        
        ```c
        // index.js
        
        const express = require('express');
        const app = express();  // Create an instance of Express
        const port = 3000;      // Define the port for the server to listen on
        
        // Basic middleware to handle requests
        app.use(express.json());  // Middleware to parse JSON in requests
        
        // Start the server
        app.listen(port, () => {
            console.log(`Server is running on http://localhost:${port}`);
        });
        ```
        
        #### **Explanation**:
        
        * `const express = require('express')`: Import Express into your application.
            
        * `const app = express()`: Create an instance of Express that will handle requests.
            
        * `app.listen(port, callback)`: This tells Express to listen for incoming requests on the specified port.
            
    
    ---
    
    ### **3\. Understanding the Port**
    
    When we run a web server, it needs to listen on a specific **port** to receive HTTP requests. Ports are like "doorways" for communication between the client (browser) and the server.
    
    * **Common Ports**: Port `3000` is commonly used in development environments.
        
    * In this example, the server will listen on **port 3000**:
        
        ```c
        const port = 3000;
        ```
        
    * When the server is running, you can access your app via [`http://localhost:3000`](http://localhost:3000) in a browser or use tools like Postman to send requests to this port.
        
    
    ---
    
    ### **4\. Routing in Express (without Dynamic Routing)**
    
    Routing is the process of defining how your server should respond to different HTTP requests (like `GET`, `POST`, etc.) on specific URLs.
    
    #### **Basic Routing Example:**
    
    Now, let’s add some basic routes in Express. A route defines what happens when an HTTP request is made to a certain URL (endpoint).
    
    ```c
    // Define a basic route for GET requests to the root URL '/'
    app.get('/', (req, res) => {
        res.send('Welcome to the Express App!');  // Send a simple response
    });
    
    // Define another route for GET requests to '/about'
    app.get('/about', (req, res) => {
        res.send('This is the About page');
    });
    ```
    
    #### **Explanation:**
    
    * `app.get('/', callback)`: This sets up a route to handle `GET` requests to the root URL (`/`). When the user visits [`http://localhost:3000/`](http://localhost:3000/), they will see the message "Welcome to the Express App!"
        
    * `app.get('/about', callback)`: This sets up another route for the `/about` page.
        
    
    Now, you can try visiting [`http://localhost:3000/`](http://localhost:3000/) and [`http://localhost:3000/about`](http://localhost:3000/about) to see the responses.
    
    ---
    
    ### **5\. Work for Students: Basic Routing Practice**
    
    Ask your students to create a few routes:
    
    1. A `GET` route for `/home` that returns "This is the Home page".
        
    2. A `GET` route for `/contact` that returns "This is the Contact page".
        
    3. A `GET` route for `/services` that returns "This is the Services page".
        
    
    **Tip**: Have them think about the structure of their routes and practice how the `req` (request) and `res` (response) objects are used.
    
    ---
    
    ### **6\. Dynamic Routing in Express**
    
    Dynamic routing allows you to create routes that can change based on variables in the URL. You use **route parameters** to define dynamic routes.
    
    For example, if you wanted to create a route for user profiles based on their username, you can use a dynamic route like this:
    
    ```c
    // Define a route with a dynamic parameter (username)
    app.get('/user/:username', (req, res) => {
        const username = req.params.username;  // Access the username parameter
        res.send(`Welcome, ${username}!`);  // Send a personalized response
    });
    ```
    
    #### **Explanation**:
    
    * `/user/:username`: The `:username` part is a **dynamic parameter**. Express will match anything in this part of the URL and make it available in `req.params`.
        
    * `req.params.username`: We access the dynamic part of the URL (the username) using `req.params.username`.
        
    
    **Example URLs**:
    
    * [`http://localhost:3000/user/johndoe`](http://localhost:3000/user/johndoe) will return "Welcome, johndoe!"
        
    * [`http://localhost:3000/user/janedoe`](http://localhost:3000/user/janedoe) will return "Welcome, janedoe!"
        
    
    This is useful for creating user profiles, posts, or any resource where the URL contains unique identifiers.
    
    ---
    
    ### **7\. Destructuring in Dynamic Routing**
    
    In JavaScript, **destructuring** allows you to extract values from objects or arrays in a more readable way. You can use destructuring to simplify how you handle route parameters.
    
    Here’s an example:
    
    ```c
    app.get('/user/:username/:age', (req, res) => {
        const { username, age } = req.params;  // Destructure parameters directly from req.params
        res.send(`User: ${username}, Age: ${age}`);
    });
    ```
    
    #### **Explanation**:
    
    * `const { username, age } = req.params`: This is destructuring. It extracts the `username` and `age` directly from the `req.params` object, making the code cleaner and easier to read.
        
    
    **Example URL**:
    
    * [`http://localhost:3000/user/johndoe/25`](http://localhost:3000/user/johndoe/25) will return "User: johndoe, Age: 25"
        
    * [`http://localhost:3000/user/janedoe/30`](http://localhost:3000/user/janedoe/30) will return "User: janedoe, Age: 30"
        
    
    ---
    
    ### **8\. Work for Students: Dynamic Routing Practice**
    
    Ask your students to create a dynamic route for displaying a product based on its ID. Here’s an example to guide them:
    
    1. A route like `/product/:id` that shows the product ID in the response.
        
        * Example: `/product/123` should show "Product ID: 123".
            
    
    ---
    
    ### **9\. Final Wrap-Up**
    
    By this point, students should have a basic understanding of:
    
    * **Setting up an Express server**.
        
    * **Creating basic routes** for handling GET requests.
        
    * **Using dynamic routes** with parameters.
        
    * **Destructuring objects** in route handlers to simplify code.
        
    
    Encourage them to experiment by adding more routes, parameters, and even try handling different HTTP methods like `POST`, `PUT`, and `DELETE`.
    
    ---
    
    ### **Summary for Students**:
    
    1. **Express Basics**: It’s a framework to make creating web servers easy in Node.js.
        
    2. **Basic Routes**: You can create routes that respond to HTTP requests.
        
    3. **Dynamic Routes**: Routes that change based on parameters in the URL.
        
    4. **Destructuring**: You can simplify the process of extracting parameters using destructuring.
        
    
    By practicing these concepts, students will be well on their way to mastering routing and handling more complex requests in Express!
    
    now explain about the middleware for now explain about the built in middleware and also about the ejs engine and many more
    
    ###### \]
    
    ### **1\. Understanding Middleware in Express**
    
    Middleware functions are functions that have access to the **request (req)** and **response (res)** objects, as well as the **next function** in the application’s request-response cycle. They can modify the request, the response, or even stop the request-response cycle.
    
    In Express, middleware is typically used for tasks like logging, parsing request bodies, handling authentication, error handling, etc.
    
    #### **Middleware Workflow**:
    
    1. **Request** is received by the server.
        
    2. The middleware processes the request.
        
    3. The middleware decides to either:
        
        * Pass the request to the next middleware or route handler by calling `next()`.
            
        * Send a response without calling `next()`.
            
    
    Middleware functions are executed in the order they are defined, and each middleware function can either:
    
    * Modify the request/response.
        
    * End the request-response cycle.
        
    * Call `next()` to pass control to the next middleware function.
        
    
    ---
    
    ### **2\. Built-in Middleware in Express**
    
    Express comes with several built-in middleware that you can use out of the box. Here are some commonly used built-in middleware functions:
    
    #### **a.** `express.json()` Middleware
    
    This middleware is used to parse incoming JSON data in the request body. It is particularly useful when handling `POST` requests with JSON payloads.
    
    ```c
    app.use(express.json());  // Middleware to parse incoming JSON data
    ```
    
    * **Explanation**: This will automatically parse any JSON data that comes with the request body, and you can access it using `req.body`. For example, if a client sends `{ "name": "John" }`, you can access [`req.body.name`](http://req.body.name) to get `"John"`.
        
    
    #### **b.** `express.urlencoded()` Middleware
    
    This middleware is used to parse incoming requests with `urlencoded` payloads. It’s often used with forms that submit data in `application/x-www-form-urlencoded` format.
    
    ```c
    app.use(express.urlencoded({ extended: true }));
    ```
    
    * **Explanation**: This middleware parses data sent from HTML forms, making the form data accessible via `req.body`. The `extended: true` option allows for complex objects and arrays to be encoded.
        
    
    #### **c.** `express.static()` Middleware
    
    This middleware serves static files (such as images, CSS, and JavaScript files) directly to the client.
    
    ```c
    app.use(express.static('public'));  // Serve static files from the 'public' folder
    ```
    
    * **Explanation**: This tells Express to look in the `public` folder for static files and serve them to clients. For example, if you have `public/style.css`, it can be accessed via [`http://localhost:3000/style.css`](http://localhost:3000/style.css).
        
    
    #### **d.** `app.use()` for Custom Middleware
    
    You can also write your own custom middleware. Here’s an example of logging middleware:
    
    ```c
    app.use((req, res, next) => {
        console.log(`Request received at ${req.url} - Method: ${req.method}`);
        next();  // Pass control to the next middleware or route
    });
    ```
    
    * **Explanation**: This middleware logs every request’s URL and method. It calls `next()` to pass control to the next middleware or route handler.
        
    
    ---
    
    ### **3\. Understanding EJS (Embedded JavaScript) Template Engine**
    
    **EJS** is a simple templating engine that allows you to embed JavaScript code into your HTML. It is useful for generating dynamic content on the server side, rendering data from the backend into the views (HTML pages) sent to the client.
    
    #### **Setting Up EJS in Express**:
    
    To use EJS, you first need to install it:
    
    ```c
    npm install ejs
    ```
    
    Then, you need to tell Express to use EJS as the view engine:
    
    ```c
    app.set('view engine', 'ejs');
    ```
    
    This tells Express to use EJS templates for rendering views.
    
    #### **Creating a Simple EJS Template**:
    
    1. **Create the** `views` folder: In your project, create a folder named `views` to store your EJS templates.
        
    2. **Create an EJS Template**: Create a new file `index.ejs` inside the `views` folder with the following content:
        
    
    ```c
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Welcome Page</title>
    </head>
    <body>
        <h1>Welcome, <%= name %>!</h1>
        <p>This is the home page of our Express app.</p>
    </body>
    </html>
    ```
    
    * **Explanation**: In the above EJS template, `<%= name %>` is a placeholder for dynamic content. When you render the page, it will be replaced by the value passed to it in the Express route handler.
        
    
    3. **Rendering EJS Templates in Express**: You can render the EJS template in your route handler like this:
        
    
    ```c
    app.get('/', (req, res) => {
        const userName = 'John Doe';  // This can come from your database or API
        res.render('index', { name: userName });  // Render the 'index.ejs' file with dynamic data
    });
    ```
    
    * **Explanation**: `res.render('index', { name: userName })` will render the `index.ejs` template, passing the `name` variable to the template. EJS will replace `<%= name %>` with the value of `userName`, resulting in a dynamic page.
        
    
    #### **Directory Structure**:
    
    Your project should look like this:
    
    ```c
    arduinoCopy codeexpress_app/
    ├── index.js              // Express app file
    ├── views/
    │   └── index.ejs         // EJS template file
    └── public/               // Static files (e.g., CSS, images)
        └── style.css
    ```
    
    ---
    
    ### **4\. Using EJS with Express for Dynamic Views**
    
    Let’s expand a little more on how you can use dynamic data with EJS. Suppose you want to render a list of users dynamically.
    
    1. **Create a new EJS template** (`users.ejs`):
        
    
    ```c
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Users List</title>
    </head>
    <body>
        <h1>List of Users</h1>
        <ul>
            <% users.forEach(user => { %>
                <li><%= user.name %></li>
            <% }) %>
        </ul>
    </body>
    </html>
    ```
    
    2. **Render this template in Express**:
        
    
    ```c
    app.get('/users', (req, res) => {
        const users = [
            { name: 'Alice' },
            { name: 'Bob' },
            { name: 'Charlie' }
        ];
        res.render('users', { users });  // Pass the users array to the EJS template
    });
    ```
    
    * **Explanation**: The `users` array is passed into the `users.ejs` template. Inside the EJS template, we use `<% %>` to loop through the users and display each one inside an unordered list (`<ul>`).
        
    
    ---
    
    ### **5\. Additional Built-in Middleware Examples**
    
    #### `express.Router()` Middleware:
    
    This is useful for organizing routes in modular, reusable chunks.
    
    ```c
    const router = express.Router();
    
    router.get('/products', (req, res) => {
        res.send('Product List');
    });
    
    router.get('/products/:id', (req, res) => {
        res.send(`Product ID: ${req.params.id}`);
    });
    
    // Use the router
    app.use('/api', router);  // All routes defined in the router will be prefixed with '/api'
    ```
    
    * **Explanation**: The `express.Router()` function helps you create route modules. In this example, routes under `/api/products` are handled by the router.
        
    
    #### **Error Handling Middleware**:
    
    Express provides built-in error-handling middleware.
    
    ```c
    //This must be the last middleware in the app
    app.use((err, req, res, next) => {
        console.error(err.stack);
        res.status(500).send('Something went wrong!');
    });
    ```
    
    * **Explanation**: This middleware catches any errors in the application and sends a 500 status with a generic error message.
        
    
    ---
    
    ### **Summary for Students**
    
    1. **Middleware**:
        
        * Middleware functions allow you to modify the request/response or end the request-response cycle.
            
        * Express provides built-in middleware like `express.json()` for parsing JSON and `express.static()` for serving static files.
            
    2. **EJS**:
        
        * EJS allows you to embed JavaScript inside HTML templates, making your views dynamic.
            
        * You can pass dynamic data (like user names, lists, etc.) to your EJS templates using `res.render()`.
            
    3. **Using Middleware & EJS Together**:
        
        * Middleware functions handle different parts of the request-response cycle.
            
        * EJS renders dynamic content based on data passed from your Express routes.
            
    
    By using middleware and templating engines like EJS, you can build powerful, dynamic web applications in Express!
