CodeNewbie Community 🌱

Jhon Lap
Jhon Lap

Posted on

How to Build a YouTube Clone Using Node.js

let’s build a simple YouTube-like clone using Node.js. I’ll walk you through the architecture, the backend (file upload + video streaming + REST APIs), a minimal frontend for uploading & playing videos, auth basics, and deployment tips. All code is copy-paste ready and focused on clarity and practicality you can extend features later (comments, search, recommendations, transcoding, CDN, etc.)

1. Setup

Install dependencies:

npm init -y
npm i express mongoose multer bcryptjs jsonwebtoken dotenv cors
Enter fullscreen mode Exit fullscreen mode

Create folders:

youtube-clone/
β”œβ”€ server.js
β”œβ”€ routes/
β”‚  β”œβ”€ auth.js
β”‚  └─ videos.js
β”œβ”€ models/
β”‚  β”œβ”€ User.js
β”‚  └─ Video.js
β”œβ”€ public/
β”‚  β”œβ”€ index.html
β”‚  β”œβ”€ upload.html
β”‚  └─ player.html
└─ uploads/

Enter fullscreen mode Exit fullscreen mode

.env

PORT=4000
MONGO_URI=mongodb://localhost:27017/youtube_clone
JWT_SECRET=secret
UPLOAD_DIR=uploads
Enter fullscreen mode Exit fullscreen mode

2. Models

models/User.js

const mongoose=require('mongoose');
const bcrypt=require('bcryptjs');
const UserSchema=new mongoose.Schema({
 name:String,email:String,passwordHash:String
});
UserSchema.methods.verifyPassword=function(p){return bcrypt.compare(p,this.passwordHash)};
module.exports=mongoose.model('User',UserSchema);
Enter fullscreen mode Exit fullscreen mode

models/Video.js

const mongoose=require('mongoose');
const VideoSchema=new mongoose.Schema({
 title:String,filename:String,mimeType:String,uploader:{type:mongoose.Schema.Types.ObjectId,ref:'User'},likes:{type:Number,default:0},views:{type:Number,default:0}
});
module.exports=mongoose.model('Video',VideoSchema);
Enter fullscreen mode Exit fullscreen mode

3. Routes

Auth (routes/auth.js)

const express=require('express'),router=express.Router(),User=require('../models/User'),jwt=require('jsonwebtoken'),bcrypt=require('bcryptjs');
const secret=process.env.JWT_SECRET;
router.post('/signup',async(req,res)=>{
 const {name,email,password}=req.body;
 const hash=await bcrypt.hash(password,10);
 const user=await User.create({name,email,passwordHash:hash});
 const token=jwt.sign({id:user._id},secret);
 res.json({token});
});
router.post('/login',async(req,res)=>{
 const {email,password}=req.body;
 const user=await User.findOne({email});
 if(!user||!await user.verifyPassword(password))return res.status(401).json({error:'Invalid'});
 const token=jwt.sign({id:user._id},secret);
 res.json({token});
});
module.exports=router;

Enter fullscreen mode Exit fullscreen mode

*Video *(routes/videos.js)
const

express=require('express'),router=express.Router(),multer=require('multer'),fs=require('fs'),path=require('path'),Video=require('../models/Video');
const upload=multer({dest:'uploads/'});
router.post('/upload',upload.single('video'),async(req,res)=>{
 const v=await Video.create({title:req.body.title,filename:req.file.filename,mimeType:req.file.mimetype});
 res.json(v);
});
router.get('/',async(req,res)=>res.json(await Video.find()));
router.get('/:id/stream',async(req,res)=>{
 const v=await Video.findById(req.params.id);
 const file=path.join('uploads',v.filename);
 const stat=fs.statSync(file);const range=req.headers.range;
 if(range){const [start,end]=range.replace(/bytes=/,'').split('-').map(Number);
 const s=start,e=end||stat.size-1;const chunk=e-s+1;
 res.writeHead(206,{'Content-Range':`bytes ${s}-${e}/${stat.size}`,'Accept-Ranges':'bytes','Content-Length':chunk,'Content-Type':v.mimeType});
 fs.createReadStream(file,{start:s,end:e}).pipe(res);}else{
 res.writeHead(200,{'Content-Length':stat.size,'Content-Type':v.mimeType});
 fs.createReadStream(file).pipe(res);
}});
module.exports=router;
Enter fullscreen mode Exit fullscreen mode

If you want to download youtube video in your gallary download Snaptube apk.

4. Server Setup

server.js

require('dotenv').config();
const express=require('express'),mongoose=require('mongoose'),cors=require('cors'),path=require('path');
const auth=require('./routes/auth'),videos=require('./routes/videos');
const app=express();
app.use(cors());app.use(express.json());
app.use('/api/auth',auth);
app.use('/api/videos',videos);
app.use(express.static('public'));
mongoose.connect(process.env.MONGO_URI).then(()=>app.listen(4000));
Enter fullscreen mode Exit fullscreen mode

5. Frontend (simplified)

public/index.html

<h1>YouTube Clone</h1>
<a href="/upload.html">Upload Video</a>
<div id="list"></div>
<script>
fetch('/api/videos').then(r=>r.json()).then(vs=>{
 document.getElementById('list').innerHTML=vs.map(v=>`<p>${v.title} - <a href="player.html?id=${v._id}">Play</a></p>`).join('');
});
</script>
Enter fullscreen mode Exit fullscreen mode

public/player.html

<video id="v" controls></video>
<script>
const id=new URLSearchParams(location.search).get('id');
document.getElementById('v').src=`/api/videos/${id}/stream`;
</script>
Enter fullscreen mode Exit fullscreen mode

Final Words

Building a YouTube clone with Node.js is a great way to understand how modern video platforms work behind the scenes. This project demonstrates how file uploads, video streaming, and API-based architectures come together to create a functional media service.

While this version covers the basics, you can enhance it further by adding user authentication, thumbnails, comments, search functionality, and cloud storage support. With each improvement, you’ll get closer to a professional-level streaming platform β€” and strengthen your full-stack development skills in the process.

gg

Top comments (0)