Node.js

Node.js is a cross-platform runtime environment that allows you to run JavaScript outside of a web browser—usually on a server. It enables developers to build fast, scalable server-side and network applications using JavaScript.
extension → .js (any js file).

node REPL

REPL stands for: Read → Eval → Print → Loop. The Node.js REPL is an interactive shell that lets you run JavaScript line-by-line directly in the terminal.

How to Start REPL:

  1. Open your terminal
  2. Type: node
  3. You'll see a > prompt. Start typing JavaScript code.
  4. To exit REPL, press: Ctrl + C (twice) or type .exit

to run Javascript with node in terminal use "node fileName.js". You need to be in same folder where file is present

process Object

In Node.js, the process object is a global object that provides information and control over the current Node.js process. It's part of the core process module, so you don't need to import it.

Key Properties of the process Object

process.argv: An array containing the command-line arguments passed when the Node.js process was launched. The first element is the path to the Node.js executable, the second is the path to the script, and subsequent elements are additional arguments.

Example: // Example: node script.js arg1 arg2 console.log(process.argv); //Output like: ['node', 'path/to/script.js', 'arg1', 'arg2']

There are many more properties and Methods in process Object...

Export in files

In Node.js, module.exports and require() are core concepts for creating and using modules to organize and share code.

module.exports

module.exports is an object in a Node.js module that defines what a module exposes to other parts of the application. By default, it's an empty object ({}), but you can assign functions, objects, or values to it.

Purpose: It determines what gets returned when another file uses require() to import the module.
Location: Every Node.js file has a module object, and module.exports is a property of it.

1. Example: Exporting a Single Function // math.js function add(a, b) {   return a + b; } module.exports = add; // Export the function 2. Example: Exporting Multiple Items const add = (a, b) => a + b; const subtract = (a, b) => a - b; module.exports = {   add,   subtract }; // Export an object with multiple functions 3. Alternative: Using exports Shorthand exports is an alias for module.exports. You can use it to add properties but cannot reassign it directly. exports.add = (a, b) => a + b;

require()

require() is a function used to import modules, whether they are built-in (e.g., fs, http), installed via npm, or local files.

Syntax:

const moduleName = require('path-or-module-name');

1. Example: Importing a Module // app.js const math = require('./math'); // Import math.js (local file, relative path) console.log(math.add(2, 3)); // 5
2. Importing Built-in or npm Modules const fs = require('fs'); // Built-in module const express = require('express'); // npm-installed module

import

the import statement is used to bring in modules, functions, or variables from other files or packages, is part of the ECMAScript module system, introduced to standardize module handling in JavaScript. It's an alternative to the CommonJS require() system used in Node.js by default.

To use import, you must configure your project for ES Modules:

  • Option 1: Set "type": "module" in package.json. (All .js files are treated as ES Modules, and you use import/export instead of require()/module.exports.)
  • Option 2: Use .mjs Extension. Name your files with .mjs to explicitly indicate ES Modules, even without "type": "module". Example: app.mjs instead of app.js.

import vs require()

  • We can't selectively load only the pieces we need with require but with import, we can selectively load only the pieces we need, which can save memory.
  • Loading is synchronous for 'require' but can be asynchronous for 'import'. there are other differences also.
Example: (use .js if "type": "module" is set in package.json file OR use .mjs) 1. Importing from a Local File: // utils.js export const add = (a, b) => a + b; export const subtract = (a, b) => a - b; // app.js import { add } from './utils.js'; //we can import only selective things (import add here but not subtract). console.log(add(2, 3)); // 5
2.Importing from an npm Package: npm install lodash // app.js import { map, filter } from 'lodash'; //imported multiple console.log(map([1, 2, 3], n => n * 2)); // [2, 4, 6]

Export in directories

When organizing large projects, you often group files into folders. You can export modules from an entire directory using a special file: index.js. It acts as the entry point of the folder.

Steps:

  1. Create an index.js file inside the directory from which you want to export modules.
  2. Import the modules (functions, variables, classes, etc.) from other files in that directory into index.js, and export them together using module.exports.
  3. Import the directory (folder) wherever needed — Node.js will automatically look for index.js inside that folder.
Example: //file structure project/ ├── utils/ │ ├── math.js │ ├── string.js │ └── index.js ├── app.js //utils/math.js const add = (a, b) => a + b; module.exports = { add }; // utils/string.js const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1); module.exports = { capitalize }; // utils/index.js const math = require('./math'); import all in one file const string = require('./string'); module.exports = { //export math: math, string: string }; // app.js const utils = require('./utils'); //import folder console.log(utils.math.add(2, 3)); // 5 console.log(utils.string.capitalize('hello')); // 'Hello'

There are other way also other than index.js...

NPM (Node Package Manager)

It is default package manager for Node.js, A large online library of packages (modules), A command-line tool to install, manage, and publish packages

A package is like a ready-made tool or library that you can install and use in your project instead of writing the code yourself.

Registry: The npm registry (https://www.npmjs.com) hosts over 2 million packages, which are reusable JavaScript modules.

Installing Packages

Locally(Preffered way):
npm install package-name
OR npm i package-name (i is alias for install)

Install in same folder of project. Locak install not work outside.

Example: npm install express

To Install globally:
npm install -g package-name
then use - npm link package-name (need to link with the folder in which we want to use)

files/folders while installing

node_modules/ is the folder where all installed packages are stored. It also includes sub-dependencies — packages required by other packages. You should NOT edit anything inside this folder manually. The node modules folder contains every installed dependency for your.

package-lock.json It records the exact version of every installed dependency, including its sub-dependencies and their versions.
there may many other things may install...

package.json Purpose: package.json is a JSON file that stores metadata about a Node.js project, including: Project name, version, description and Dependencies e.t.c
There's no need to transfer the node_modules folder if package.json is present — just run npm install to reinstall all dependencies.

Creating package.json with npm init: Command: npm init
It Interactively prompts for details like name, version, description, entry point, etc. Generates a package.json file based on your input.

Express.js

Express is a minimal and flexible web application framework for Node.js, designed to simplify the process of building server-side applications and APIs.

Library

A library is a set of reusable code that you call to perform specific tasks — you control the flow of the program. e.g - axios e.t.c.

Framework

A framework is a complete structure that calls your code at the right time — it controls the flow, and you follow its rules. e.g - express e.t.c.

Setup for express:

  • Step 1: Create a New Project Folder
  • Step 2: Initialize package.json
  • Step 3: Install Express.js: Install Express as a dependency.
  • Step 4: Create a js file In the same folder.
  • Step 5: Run Your Express App:
    In the terminal - node filename OR
    Open a browser and go to: http://localhost:portNumber
    (you can acces you local computer server using localhost)
Example code in js file: const express = require('express'); const app = express(); //name "app" is used generally we can also use other name console.log(app); //it shows a large object that represents the internal structure of the Express app. It includes: All built-in methods, Properties, Event listeners e.t.c. // Define a route app.get('/', (req, res) => {   res.send('Hello from Express!'); }); // Start the server app.listen(3000, () => {   console.log('Server is running at http://localhost:3000'); });

listen()

listen() is a method that starts your Express server and makes it listen for incoming requests on a specified port.
Syntax - app.listen(port, [callback])

nodemon

nodemon is a utility for Node.js that automatically restarts your application when file changes in the directory are detected.

  • To install - npm install -g nodemon (installing globally recommended)
  • To run file with nodemon - nodemon filename.js

Handling Requests in Express.js

In Express, handling requests means defining what your server should do when it receives a specific type of request (like a user visiting a page or submitting a form).

Basic Syntax:

app.METHOD(PATH, HANDLER)

  • METHOD: HTTP method (get, post, put, delete, etc.)
  • PATH: URL path (like '/', '/login', '/products')
  • HANDLER: Function that runs when the route is matched
Example: Handling a GET Request: app.get('/', (req, res) => {   res.send('Welcome to the homepage!'); });

Understanding Request & Response Objects

  • req → request info from the client
  • res → used to send a response back

app.use()

app.use() is used to handle all types of requests (GET, POST, etc.) for a specific path or globally — especially useful when you want to do something before reaching the final route (like logging, authentication, etc.).

Basic Structure example: app.use((req, res) => {   console.log('Middleware triggered'); });

Sending Responses in Express.js

In Express, you send responses using the res (response) object, which is provided in every route handler.

Common Methods to Send Responses

1. res.send()

Sends a text, HTML, or object e.t.c response. Automatically sets the Content-Type based on the data type.

example: app.get('/', (req, res) => {   res.send('/ means Home Page in paths'); });

2. res.redirect()

Redirects the client to another URL. Default status is 302 (temporary redirect).

example: app.get('/old-route', (req, res) => {   res.redirect('/new-route'); });

There are other methods/ways also...

Single Response: Only one response can be sent to one path per request. Calling res.send or similar methods multiple times causes an error.

Routing

Routing in Express.js is the process of defining how an application responds to client requests to specific URLs (paths) using specific HTTP methods like GET, POST, etc.

  • Routes are defined using methods of the app object corresponding to HTTP methods (app.get(), app.post(), app.put(), app.delete(), etc.).
  • Each route maps a URL pattern to a handler function that processes the request and sends a response.
  • Route paths can be strings, string patterns, or regular expressions. e.g - / matches the root path, /users matches requests to /users, /user/:id matches dynamic paths like /user/123, where :id is a route parameter.
example: // GET request to the root path app.get('/', (req, res) => {   res.send('Welcome to the homepage!'); }); // request with a route parameter app.get('/user/:id', (req, res) => {   res.send(`User ID: ${req.params.id}`); }); // Catch-all route for all unmatched paths app.get('*', (req, res) => {   res.status(404).send('404 - Page Not Found'); });

The app.get('*', ...) route matches any GET request to any path that hasn't been handled by previous routes.

Route Parameters

In Express, route parameters (also called path parameters) allow you to capture dynamic values from the URL.

They are defined in the route path using a colon (:) followed by the parameter name. These parameters become available in the req.params object in your route handler.

Syntax:

app.get('/route/:paramName', (req, res) => {
  // to Access full object - req.params
  // to only Access paramName - req.params.paramName
});

example: // Route with a path parameter app.get('/users/:userId', (req, res) => {   const userId = req.params.userId; // Access the parameter   res.send(`User ID: ${userId}`); }); Explanation: :userId in the route path captures the value 123 from the URL and stores it in req.params.userId.
//Multiple Path Parameters: app.get('/users/:userId/posts/:postId', (req, res) => {   const { userId, postId } = req.params;   res.send(`User ID: ${userId}, Post ID: ${postId}`); });

Optional Parameters: To make a parameter optional, add a ? after it.

example: //optional perematers app.get('/files/:fileName?', (req, res) => {   const fileName = req.params.fileName || 'default.txt';   res.send(`File: ${fileName}`); });
//Regular Expression in Parameters app.get('/items/:id(\\d+)', (req, res) => {   const id = req.params.id;   res.send(`Item ID: ${id}`); });

Note - Path parameters are different from query parameters (e.g., ?key=value), which are accessed via req.query.

Query Strings in Express

In Express, query strings are key-value pairs in a URL that come after a ? (e.g., ?key1=value1&key2=value2). They are used to pass additional data to the server and are accessible in Express via the req.query object.

//example syntax app.get('/route', (req, res) => {   // Access query parameters via req.query   const queryParams = req.query;   res.send(queryParams); });
example: app.get('/search', (req, res) => {   const { q, page } = req.query; // Destructure query parameters   res.send(`Search Query: ${q}, Page: ${page || 1}`); });
// Default values app.get('/filter', (req, res) => {   const { sort = 'asc', limit = 10 } = req.query; // Default values   res.send(`Sort: ${sort}, Limit: ${limit}`); });

Optional Query Parameters: Query parameters are inherently optional. If not provided, req.query.key is undefined.

Query Strings vs. Path Parameters
Query Strings Path Parameters
Optional, used for filtering, sorting, or searching (e.g., /search?q=term) Part of the URL path, used for identifying resources (e.g., /users/:id)
req.query req.perams

GET/POST Request in express

Get Request

An HTTP method used to retrieve data from a server. It sends parameters via the URL query string (e.g., /resource?key=value).

In Express.js, app.get('/path', (req, res) => {...}) handles these requests, accessing parameters through req.query.

It's idempotent (repeated requests yield the same result), suitable for fetching resources like web pages or API data, but less secure for sensitive data as parameters are visible in URLs.

//example: //html: <h2>GET Form</h2> <form action="http:localhost:3000/register" method="GET">   <label>User: <input type="text" name="user"></label>   <label>Password: <input type="password" name="password"></label>   <button type="submit">Submit (GET)</button> </form>
// server.js const express = require('express'); const app = express(); const port = 3000; // GET: Handle form submission app.get('/register', (req, res) => {   const { user, password } = req.query; //access data using req.query   res.send(`GET: Welcome ${user}!`); }); app.listen(port, () => console.log(`Server on port ${port}`));

Post Request

An HTTP method used to submit data to a server to create or update resources. Data is sent in the request body, supporting formats like JSON or URL-encoded form data.

In Express.js, app.post('/path', (req, res) => {...}) handles these requests, accessing data via req.body (requires middleware like express.json() or express.urlencoded()).

It's non-idempotent (repeated requests may create multiple resources) and ideal for secure data submission, such as forms or API payloads.

//example: //html: <h2>POST Form</h2> <form action="http:localhost:3000/register" method="POST">   <label>User: <input type="text" name="user"></label>   <label>Password: <input type="password" name="password"></label>   <button type="submit">Submit (GET)</button> </form>
// server.js const express = require('express'); const app = express(); const port = 3000; // Middleware to parse form data and JSON app.use(express.urlencoded({ extended: true })); app.use(express.json()); //use these otherwise data is not accessible and it shows Undefined // POST: Handle form submission app.post('/register', (req, res) => {   const { user, password } = req.body; // access data using req.body   res.send(`POST: Welcome ${user}!`); }); app.listen(port, () => console.log(`Server on port ${port}`));

EJS(Embedded JavaScript)

EJS (Embedded JavaScript) is a templating engine for Node.js that lets you generate HTML dynamically by embedding JavaScript directly in your templates. It's lightweight, works well with Express.js, and is great for rendering dynamic web pages with data from your server.

File Extension - .ejs

To Install - npm install ejs
We need to require express to use this because it automatically requires ejs.

Example setup: const express = require('express'); const app = express(); // Set EJS as the templating engine app.set('view engine', 'ejs'); app.set('views', './views'); // Setting the folder for EJS templates (commonly named 'views', but you can use any folder name) OR app.set('views', './templates'); // if your EJS files are in a 'templates' folder

to run ejs from other directory:

To run an EJS-based Express app from a parent directory, you need to ensure the Express server correctly locates the EJS templates and other resources, even when the server is started from a directory outside the project folder.

example: const express = require('express'); const path = require('path'); //require path first const app = express(); app.set('view engine', 'ejs'); // Set the views directory using an absolute path app.set('views', path.join(__dirname, 'views')); //set this always

res.render()

The res.render method in Express.js is used to render a view template (like an EJS file) and send the resulting HTML to the client.

Syntax:

res.render('templateName', dataObject);
'templateName' → the name of your .ejs file (without .ejs)
dataObject → an optional object containing data to use in the template.

example: const express = require("express"); const app = express(); const path = require("path"); app.set("view engine", "ejs"); app.set("views", path.join(__dirname, "views")); //this app.get("/", (req, res) => {   res.render("home", { name: "Inderjit", age: 20 }); }); //OR like this app.get("/support", (req, res) => {   res.render("support"); }); app.listen(3000, () => {   console.log("Server running on http://localhost:3000"); });

Interpolation Syntax

Interpolation syntax in EJS refers to the method of embedding dynamic values (such as variables or expressions or server-side values) directly into HTML templates using special EJS tags. It allows server-side data to be inserted into the rendered HTML output.

There are two main interpolation tags:

1. <%= %> — Escaped Output Tag

Prints the evaluated value of a variable or expression. HTML characters like <,>, &, etc., are escaped (converted to safe entities like &lt;). Safe to use with user data to prevent XSS (cross-site scripting).

example: <%= "<h1>Welcome</h1>" %> //output for html: &lt;h1&gt;Welcome&lt;/h1&gt; //It shows the string as plain text, not HTML. //in browser <h1>Welcome</h1>

2. <%- %> — Unescaped Output Tag

Prints the evaluated value as raw HTML. Useful when you want to render actual HTML from a variable. Not safe for user input unless sanitized — it can expose your page to XSS attacks.

example: <%- "<h1>Welcome</h1>" %> //output for html: <h1>Welcome</h1> //It shows in bold after h1 works. //in browser

Welcome

Control & Utility Tags

Used for Logic or Structure. These tags are used not to display data, but to control the flow of logic, structure your templates, or manage whitespace/comments. These are essential for adding loops, conditions, comments, and clean formatting in templates.

1. <% %> - Scriptlet Tag (Control-Flow, No Output)

Executes JavaScript for control flow (e.g., loops, conditionals, variable assignments) without directly outputting to the HTML.

example: <% if (user.isAdmin) { %>   <p> Welcome, Admin! </p> <% } %>

2. <%_ %> - Whitespace Slurping Scriptlet Tag

Removes all whitespace (spaces, newlines) before the tag, useful for clean HTML output.

example: <ul<   <%_ notes.forEach(note => { %>     <li><%= note.title %></li>   <%_ }) %> </ul> //output for html like: <ul>   <li>JavaScript Async/Await</li> </ul> //without it may like: <ul>   <li>JavaScript Async/Await</li> </ul>

3. <%# %> - Comment Tag

Adds comments in EJS that are not included in the rendered HTML and are not executed.

example: <%# This is a comment, not visible in the HTML %> <p>Visible content</p> //output for html like: <p>Visible content</p>

4. <%% %> - Outputs a Literal

Escapes the <% delimiter, rendering it as literal text in the output. If you want to print a literal <% in the HTML (for educational content or documentation), use <%%.

example: <%%= "example" %> //output: <%= "example" %>

5. %> - Plain Ending Tag

Closes any EJS tag (<%, <%_, <%=, <%-, etc.).

6. -%> - Trim-Mode (Newline Slurp) Tag

Removes the newline character after the tag, reducing extra line breaks in the output, helping keep HTML compact.

example: <ul<   <%_ notes.forEach(note => { %>     <li><%= note.title %></li>   <%_ }) %> </ul> //output for html like: <ul>   <li>JavaScript Async/Await</li> </ul> //without it may like: <ul>   <li>JavaScript Async/Await</li> </ul>

7. _%> - Whitespace Slurping Ending Tag

Like -%>, but removes all whitespace after the tag, not just the newline. Useful for super clean output.

example: <ul<   <%_ notes.forEach(note => { %>     <li><%= note.title %></li>   <%_ }) %> </ul> //output for html like: <ul>   <li>JavaScript</li><li>Python</li> </ul>

Passing data to ejs

In EJS, data is passed from the Express server to the template via the res.render method.

res.render()

The res.render method in Express.js is used to render a view template (like an EJS file) and send the resulting HTML to the client.

Syntax:

res.render('templateName', dataObject);
'templateName' → the name of your .ejs file (without .ejs)
dataObject → an optional object containing data to use in the template.

example: const express = require("express"); const app = express(); const path = require("path"); app.set("view engine", "ejs"); app.set("views", path.join(__dirname, "views")); app.get("/", (req, res) => {   res.render("home", { name: "Inderjit", age: 20 }); }); app.listen(3000, () => {   console.log("Server running on http://localhost:3000"); }); //views/home.ejs <p>Welcome, <%= name %>!</p> <p>Your age is <%= age %>.</p> //output:

Welcome, Inderjit!

Your age is 20.

In EJS, the variable name in the template and the key in the object passed to res.render() should match.

If the key and value names are the same in the object, you can use shorthand syntax and write only one.

Example: app.get("/", (req, res) => {   const random = Math.random();   res.render("home", { random }); // shorthand for { random: random } }); // views/home.ejs <p>Random number: <%= random %></p>

Include

In EJS , the <%- include %> syntax is used to include one EJS file inside another. This is helpful for reusing common layouts like headers, footers, or navigation menus.

Syntax:

<%- include('path/to/file') %>

example: //index.ejs: <%- include('partials/header') %> //include header ejs <p>Welcome to My Website</p> <%- include('partials/footer') %> //include footer ejs //header.ejs: <header>   <p>This is the header</p> </header> //footer.ejs: <footer>   <p>Footer content goes here</p> </footer>
//after rendering like: <header>   <p>This is the header</p> </header> <p>Welcome to My Website</p> <footer>   <p>Footer content goes here</p> </footer>
//in browser like:

This is the header

Welcome to My Website

Footer content goes here

Use different folder for these files like above partials folder is used or you can use "includes" also as folder name.

Passing Data to Includes

You can pass variables to included files by adding a second argument to include like:

Example: <%- include('header', { title: 'My Custom Title' }) %> //same like passing data to ejs In header.ejs, you can use the passed variable like: <header> <h1> <%= title %> </h1> </header>

REST

REST (Representational State Transfer) is a widely used architectural style for designing web APIs, networked applications, particularly web services. It relies on a stateless, client-server communication model, usually over HTTP.

Key principles include:

  • Resource-Based: Everything is treated as a resource, and each resource is identified by a URI (Uniform Resource Identifier), like /users/1.
  • Stateless: Each request from a client to a server must contain all the information needed to process it.
  • Client-Server Architecture: The client and server operate independently. The client handles the user interface, and the server manages data and logic.
  • Representation: Resources are represented in formats such as JSON, XML, or HTML. The client interacts with the resource by using these representations.
  • Stateless Communication: No session data is stored on the server. Every request is independent.
  • Uniform Interface: A consistent way to access resources using standard HTTP methods - (CRUD operations):-
    To Retrieve data - GET (e.g., GET /users/123)
    To Create new data - POST (e.g., POST /users)
    To Update data - PUT (e.g., PUT /users/123)
    To Remove data - DELETE (e.g., DELETE /users/123)
    To Partially update a resource - PATCH

How to Creaete Unique IDs

To create unique IDs in your Express app (e.g. for each post), you have a few good options depending on how unique, readable, or persistent you want them to be.

1. Use crypto.randomUUID() (Built-in Node.js)

Use Like: //1.require: const { randomUUID } = require('crypto'); //2.use const newPost = {   id: randomUUID(), //this   username: "alice",   content: "Hello world" }; //Produces something like: "3f50d2b7-9a7e-40ae-9f0c-5071d2e426f5" //these are Universally unique, No extra dependencies

2. Use the uuid package (Very common in real projects)

Use Like: //1.Install It: npm install uuid //2.require: const { v4: uuidv4 } = require('uuid'); //3.use const newPost = {   id: uuidv4(), //this   username: "bob",   content: "Hello world" }; Output is similar to randomUUID().

3. Use a Simple Counter (for testing or in-memory arrays)

If you don't care about global uniqueness and just want simple incremental IDs (for development/testing only).

Use Like: let idCounter = 1; const newPost = {   id: idCounter++,   username: "test",   content: "Simple ID test" }; //IDs will reset every time the server restarts — not recommended for real use.

There are many other methods also...

Use PUT, PATCH, DELETE in html

Since HTML forms only support GET and POST methods via method attribute, but Express.js supports all HTTP methods (GET, POST, PUT, PATCH, DELETE), here's how you can use PUT, PATCH, and DELETE in HTML forms using a common workaround.

Method Override in Express

Use a middleware called method-override.

Step by step guide: 1. Install method-override: npm install method-override 2. Set up in your Express app: const methodOverride = require('method-override'); //require it app.use(methodOverride('_method')); // looks for _method in form fields //also we can use other name than _method but this is commom 3. Write HTML Form with POST but include _method hidden field: <form action="/users/1?_method=PUT" method="POST"> //use ?_method=PUT   //form fields </form> Or using hidden input: <form action="/users/1" method="POST">   <input type="hidden" name="_method" value="PUT">   //other form fields </form> Similarly, use _method=PATCH or _method=DELETE for other methods. 4. Define routes in Express: app.put('/users/:id', (req, res) => { //use method you want to use   res.send('User updated'); });

There are other ways also...