This project is a complex backend project that is built with nodejs, expressjs, mongodb, mongoose, jwt, bcrypt, and many more. This project is a complete backend project that has all the features that a backend project should have. We are building a complete video hosting website similar to youtube with all the features like login, signup, upload video, like, dislike, comment, reply, subscribe, unsubscribe, and many more.
- The backend is the "behind-the-scenes" part of an application (like a website or app) that users don't see, handling the logic, data storage, and server operations that make everything work, including databases, APIs, and user authentication, using languages like Python, Java, or Node.js to process requests and deliver data to the user-facing frontend.
- A database schema serves as the blueprint for a database, defining its structure and organization in a formal language supported by a database management system (DBMS). It outlines how data is logically stored, including the relationships between different tables and other database objects.
- These schemas act as blueprints for your data, specifying field types, required fields, default values, and even custom validation logic.
MongoDB Atlas is a fully managed, multi-cloud database-as-a-service that simplifies the deployment, scaling, and management of MongoDB databases. It automates tasks like provisioning, patching, backups, and scaling, allowing developers to focus on building applications instead of managing infrastructure. It is built on major cloud providers like AWS, Azure, and Google Cloud.
MongoDB is an open-source database that requires manual management, while MongoDB Atlas is a fully managed cloud-based service that automates tasks like backups, scaling, and security. The choice depends on your needs: self-hosted MongoDB offers more control and is free to start with, but comes with higher operational overhead; Atlas offers ease of use, automated scaling, and built-in features for high availability, suitable for those who prefer not to manage the infrastructure.
- Express.js, often referred to simply as Express, is a minimalist and flexible Node.js web application framework. It provides a robust set of features for building web applications and APIs quickly and efficiently.
- Express.js is a backend framework that runs on Node. js. It helps build server-side applications and APIs by handling routing, requests, and responses.
Node JS is a runtime environment that allows you to run JavaScript on the server side, while Express JS is a web application framework built on top of Node js to simplify building web applications.
- npm init
- git initialize
- third party service
- folder structure
- npm i mongoose express dotenv
- online database connection --> MongoDB ATLAS (username, password, IP Address, String connection) | database access, network access
- database coonection in codebase -->( .env = PORT, MONGODB_URI) , (constants = database's name )
- App through express, db connection through Mongodb and mongoose will connects database
- mongoose reads the MongoDB_URI from .env and mongoose.connect() connects your node.js App to mongoBD
- two approach to connect with database --> 1. write all connection code in index.js, 2. make a file(db - index.js) and import in index.js
- When we talk to the database --> try-catch / promise (Error handling) and async-await (database is in another continent)
- Error : your project uses ES Modules, and ES Modules do NOT support require() --> solve by adding experimental features inside package.json (nodemon)
- Read documentation
- Creates an Express application. The express() function is a top-level function exported by the express module.
- request: The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on.
- In this documentation and by convention, the object is always referred to as req (and the HTTP response is res) but its actual name is determined by the parameters to the callback function in which youβre working. properties - req.baseURL, req.body, req.params
- response: The res object represents the HTTP response that an Express app sends when it gets an HTTP request. - In this documentation and by convention, the object is always referred to as res (and the HTTP request is req) but its actual name is determined by the parameters to the callback function in which youβre working.
- Search npm js
- npm i cookie-parser cors
- enable CORS => This allows your frontend to talk to your backend.
- configuration setting
- comming data from multiple places into backend so we need some configurations setting and how to configure ---> .use()
- middleware
- Middleware in Node.js, particularly within frameworks like Express.js, refers to functions that have access to the request (req) object, the response (res) object, and the next() middleware function in the application's request-response cycle. These functions can perform various tasks before the request reaches its final route handler or after a response is generated.
- Types of Middleware: a. Application-level middleware: Bound to the Express application instance using app.use() b. Router-level middleware: Similar to application-level middleware but bound to an instance of express.Router(), allowing for modular routing. c. Built-in middleware: Provided by Express itself, such as express.static() for serving static files, express.json() for parsing JSON request bodies, and express. urlencoded() for parsing URL-encoded data. d. Third-party middleware: External modules installed via npm to add specific functionalities (e.g., cookie-parser for parsing cookies, cors for handling Cross-Origin Resource Sharing). e. Error-handling middleware: A special type of middleware defined with four arguments (err, req, res, next) specifically designed to catch and handle errors that occur during the request-response cycle.
- status code
- API's server have status code
- In Node.js, particularly when building web servers with frameworks like Express, HTTP status codes are used to indicate the outcome of a client's request to the server. These codes are part of the HTTP response and inform the client whether the request was successful, redirected, or encountered an error.
- data fields
- user.models.js
- video.models.js
- npm i mongoose-aggregate-paginate-v2 (A page based custom aggregate pagination library for Mongoose with customizable labels)
- mongodb aggregation pipeline
- The MongoDB Aggregation Framework is a powerful tool for processing and transforming data within MongoDB collections. It allows for complex data analysis, reporting, and transformations directly within the database, minimizing the need for extensive client-side processing.
- Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions. Middleware is specified on the schema level and is useful for writing plugins.
- npm i bcrypt jsonwebtoken
- bcrypt: A library to help you hash passwords.
- JWT: it's bearer token. (Access token, Refresh token)
- Explain the code of user models
- mongoose β Used to create MongoDB models and schemas. |for creating schemas & interacting with MongoDB.
- Schema β A blueprint/structure for how a user document should look. | Schema β shortcut for mongoose.Schema.
- jwt β Used to generate tokens for login (Access + Refresh tokens).
- bcrypt β Used to hash passwords securely.
- Hashing converts your real password into a secret, unreadable string before saving it in the database. why use - Because if someone hacks your database, they should NOT see your real passwords.
- Refresh Token : Used during silent login (access token expires β refresh token creates a new one).
- Access Token contains: user id, email, username, full name --> Used for: Authorization, Protecting routes.
- Refresh Token contains only: _id --> Used to generate new access token without login.
- salt round = 10 (industry standard):
- A salt is a random string added to the password before hashing so that:
- two users with the same password will NOT have the same hash
- attackers cannot use precomputed tables (rainbow tables)
- password β password + randomSalt β hash => This makes hashing more secure.
- Salt rounds (also called cost factor) = how many times bcrypt internally processes the password.(Higher rounds = more secure, Higher rounds = slower hashing)
- 10 rounds => It is secure enough for modern applications, It is fast enough to not slow down signup/login
- bcrypt generates a random salt internally, applies hashing 10 times, produces a secure, unique hash
- Pagination Plugin: This lets you paginate complex queries like: filter by tag, search videos, sort by views, group by categories etc.
- How to upload files in backend | file upload (file handling) | use third party server to upload like Cloudinary service
- Cloudinary is a cloud-based media management service that allows you to easily upload, store, optimize, and deliver:Images, Videos, Thumbnails, Audio, Raw files . It is widely used in modern appsβInstagram, TikTok, YouTube clones, e-commerce apps, etc.
- file upload (choose 1 package/way out of 2 packages)- express file upload and multer
- npm i cloudinary multer
- and also import fs(file system) to manage the files , use multer as node.js middleware
- Multer is a Node.js middleware that simplifies handling multipart/form-data, which is the encoding type used for file uploads. It provides middleware to process incoming data, making uploaded files and other form fields easily accessible in req.file or req.files and req.body objects, respectively.
- Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
- Multer accepts an options object, the most basic of which is the dest/storage property, which tells Multer where to upload the files.
- If you want more control over your uploads, you'll want to use the storage option instead of dest. Multer ships with storage engines DiskStorage and MemoryStorage:
- DiskStorage: The disk storage engine gives you full control on storing files to disk.
- MemoryStorage: The memory storage engine stores the files in memory as Buffer objects. It doesn't have any options.
- Operating System, network, communication / HTTP or HTTPs, client, server, IP Address
- (URL: Uniform Resource Locator, URI: Uniform Resource Identifier, URNs: Uniform Resource Names)
- URI is the general term for any identifier, while URL and URN are specific types of URIs
- HTTP Headers : (Metadata, most common headers)
- HTTP Methods
- HTTP Status code
{
- Frontend (React)
fetch("/api/login", {
method: "POST",
body: JSON.stringify({ email, password })
})
- API Route (Next.js)
export async function POST(req) {
const { email, password } = await req.json();
return NextResponse.json({ message: "OK" });
}
}
{
STEP 1: Browser creates an HTTP Request
-----------------------------------------
URL: /api/login
Method: POST
Headers: Content-Type: application/json
Body: { email, password }
STEP 2: Request sent to the Server
-----------------------------------------
Frontend --> Internet --> Server (Backend)
STEP 3: Backend processes the request
-----------------------------------------
- Validates user
- Talks to Database
- Generates token
STEP 4: Server sends HTTP Response
-----------------------------------------
Status: 200
Headers: Content-Type: application/json
Body: { "message": "Login success" }
STEP 5: Frontend receives response
-----------------------------------------
Frontend updates UI
}
- HTTP Request β what frontend sends
- Contains: β Method, β Headers, β URL, β Body
- HTTP Response β what backend returns
- Contains: β Status Code, β Headers, β Data (JSON, HTML, file, etc.)
{
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache
{
"productId": 5,
"name": "iPhone 14",
"price": 799
}
}
{
const res = await fetch("/api/login");
const data = await res.json();
if (res.status === 200) {
console.log("Login success:", data);
} else {
console.log("Error:", data.message);
}
}
- The frontend decides what to do depending on: success or failure, what data was returned, response code
{ ββββββββββββββββββββββββββββ
β CLIENT β
β (React, Next.js UI) β
ββββββββββββββ¬ββββββββββββββ
|
| HTTP Request (fetch/axios)
v
βββββββββββββββββββββββββββ
β API β
β (/api/... endpoints) β
ββββββββββββββ¬βββββββββββββ
|
v
βββββββββββββββββββββββββββ
β BACKEND β
β Business Logic, Auth β
β Controllers, Services β
ββββββββββββββ¬βββββββββββββ
|
| DB Query
v
βββββββββββββββββββββββββββ
β DATABASE β
β MongoDB, MySQL, etc β
ββββββββββββββ¬βββββββββββββ
|
| Hosted On Cloud
v
ββββββββββββββββββββββββββββ
β CLOUD β
β Vercel, AWS, Mongo Atlas β
ββββββββββββββββββββββββββββ
}
- controllers : method with HOF & helper(wrapper) --> where run --> on URL => route
- route : route create from the express, file suggestion
- Logic Building for the Register Controller => Business logic building --> Problems => broke into small steps
- Thunder Client
- Postman (we, use) --> collection share, use for data testing, How to use Postman for backend, Postman properly configure,
- Postman is a powerful API development and testing tool that simplifies the process of building, testing, and managing APIs. It allows developers to send HTTP requests, analyze responses, automate workflows, and collaborate efficiently. With support for multiple authentication methods, request body formats, and automated testing, Postman has become one of the most popular tools for modern API development.
- In Postman, you can send requests by selecting the HTTP method (GET, POST, etc.) and entering the API URL in the request bar. After clicking Send, Postman displays the serverβs response along with headers, status codes, and data.
- get user details from frontend (How? -> take data through Postman and which data we will take from user details according to the user Model)
- validation - not empty
- check if user already exist: username, email
- check for images, check for avatar
- upload them to cloudinary, avatar
- create user object - create entry in db
- remove password and refresh token field from response
- check for user creation
- return res
- req.body
- username or email
- find the user
- password check
- access token and refresh token
- send cookie
- logout
- cookie clear
- reset refresh Token(in Model)
- problem : can't do like user.findById
- solution : generate our own middleware --> this will verify the user is exist or not to logout
- middleware majorely use with route
- Middleware (authmiddleware.ts) => "Jane se pahle mujhse mil kar jana"
- Authentication with duration:
- client(1st time login) --> Access Token(A short-lived token: duration) and Refresh Token (A long-lived token- protected resource)
- server generate new access token for more time duration
- Access token is a short-lived JWT used to access protected routes. It expires quickly for security. Refresh token is a long-lived JWT stored in an HTTP-Only cookie, used to generate a new access token when the old one expires.
- user model β
- video model β
- subscription model
- channel => count: through subscriber
- subscriber => count: through channel
- changeCurrentPassword (req.body)
- getCurrentUser
- updateAccountDetails (req.user)
- updateUserAvataer (req.file)
- getUserChannelProfile (req.params)
- Aggregation (in MongoDB) means processing data in a collection to produce summarized, transformed, or combined results.
- Aggregation returns processed data (totals, averages, groups, joined data, statistics, etc.).
- Aggregation = Taking many documents β applying operations β producing meaningful results.
- Eg. : Total number of users, Average views of videos, No. of Subscriber, No. of channel (views)
- Aggregation = Powerful processing of data using multiple stages (filtering, grouping, joining, calculating) to produce analytics or transformed output.
- An aggregation pipeline is a sequence (array) of stages that process documents in a collection. Each stage transforms the documents and passes the results to the next stage β like a data-processing pipeline.
- Pipeline: an ordered array of stages [{ $match: {...} }, { $group: {...} }, ...]
- Stage: an operator that performs one step (filter, project, group, join, sort, etc.).
- Expressions: inside stages you can use powerful expressions ($sum, $cond, $map, $filter, etc.).