Node App: How to create netflix clone. Netflix clone with HTML,CSS, JS.
Tags: html, css, javascript, webdev
Published: 2021-08-08 10:17:48

Hello, Today we'll see, how we can easily create a netflix clone using HTML, CSS and JS only. No other library. We'll also use TMDB API to fetch real data from their database.

Netflix Clone, we all use netflix in our day to day life. And if you are just starting with web development. This project can be a good practice project for you. This netflix clone is a dynamic site and has everything you need for fullstack development practice. It runs on a Node.js server. It uses TMDB API for all data.

### Features

1. Looks similar to Netflix.
2. Dynamic site run on Node.js server.
3. All data is coming from TMDB API.
4. Dedicated Dynamic Movies Info page.
5. Has movie trailers, and recommendations.
6. Has smooth card slider effect.

![Capture-2 (1)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvuxqs3lyqdw5zmatl97.png) 

To see demo or you want full coding tutorial video. You can watch the tutorial below.

#Video Tutorial

{% youtube FoD33gwhu00 %}

> I appreciate if you can support me by subscribing my youtube channel. 

So, without wasting more time let's see how to code this.

#Code

As this is a node.js web app. We need NPM and Node.js in order to start with, so make sure you have them installed in your system.

So let's start with its folder structure.

### Folder Structure.

This is our folder structure.

![Folder Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e238jwve7avebhtexudz.png)

### NPM Init

Let's start with initializing NPM. So outside `public` folder, In your `root` directory, open Command Prompt or terminal. And execute. `npm init`

It will ask you for some details. You can press enter to have default project details. After executing `npm init` you  should see a `package.json` file.

Great Now install Some libraries that we need in order to create a server.

### Installing Libraries

After creating `package.json` file. Run this command.

```
npm i express.js nodemon
```

`i` - means install.
`express.js` - is a library we need to create server.
`nodemon` - is a library which allow you to run server seamlessly even after making changes to the server.

After installation complete, you should be able to see `node_modules` folder in your `root` directory.

Now open `package.json` file in your text editor. And edit it a little bit.

1. Change the value on `"main"` key to `"server.js"`.
![main](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2jkwianokykxtxc28jq.PNG)

2. Delete `"test"` cmd from `"scripts"` object. And add new cmd called `"start"` and set it value to `"nodemon server.js"`.
![scripts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9a5jupzgxdzmo53prdq.PNG)

### Server.js

After editing `package.json` create JS file `server.js` in the `root` directory.

And write this in `server.js`.

```JS
const express = require('express');
const path = require('path');

let initial_path = path.join(__dirname, "public");

let app = express();
app.use(express.static(initial_path));

app.get('/', (req, res) => {
    res.sendFile(path.join(initial_path, "index.html"));
})

app.listen(3000, () => {
    console.log('listening on port 3000......');
})
```
######Explanation
In the top, we are using `require` method to import library so that we can use it in this file. We are importing two libraries `express` and `path`.

>`path` library is used to track paths.

After done importing libraries. We are setting a variable `app` equal to `express()`, which enable all the server related features to our `app` variable. And we also have `initial_path` which is holding our `public` folder path.

After that we have, `app.use()` which is used as a middle ware And inside this we have `express.static()` which allow us to set our static directory path. In this case we are setting our `public` folder as a static path, because our `HTML` files are inside that folder.

`app.get('/')` is a listener, And in this case it is listening for a `GET` request to our root `/` path. And whenever we get any `GET` request on `/`. We will serve them `index.html` file. That's what `res.sendFile()` do.

And the last block of our `server.js` is `app.listen` which is used to add a server's listening port. In this case, we set it to `3000`. So our server will run on `localhost:3000`. Not any other port.

Now in your terminal or cmd prompt. Run `npm start` to start the server. And, open your browser to `localhost:3000`. You'll be able to see `index.html` file.

So up until now we have created our server and successfully serving our `index.html` file to `/` path.

So let's do some front end work here. Now

### Home page.

So for our Home page, we will use these files. `index.html`, `style.css`, `home.js`, `api.js`, `scroll.js`.

Let's start from `index.html` file. Start typing basic HTML structure. And after that link `style.css` file. And let's create navbar first.

```HTML
<!-- navbar -->
<nav class="navbar">
    <img src="img/logo.png" class="logo" alt="">
    <div class="join-box">
        <p class="join-msg">unlimited tv shows & movies</p>
        <button class="btn join-btn">join now</button>
        <button class="btn">sign in</button>
    </div>
</nav>
```
>Make sure your server is running, if it is not then run `npm start` in your terminal.

######Output

![navbar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frttkv28hd5mpdzmlz7m.PNG)

All the CSS properties I'll use are easy to understand. So i'll only explain you JS only. But if you have doubt in any part. Even in CSS. Feel free to ask me in discussions.

Now style the navbar
```CSS
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    width: 100%;
    position: relative;
    background: #181818;
    font-family: 'roboto', sans-serif;
}

.navbar{
    width: 100%;
    height: 60px;
    position: fixed;
    top: 0;
    z-index: 9;
    background: #000;
    padding: 0 2.5vw;
    display: flex;
    align-items: center;
}

.logo{
    height: 60%;
}

.join-box{
    width: fit-content;
    display: flex;
    justify-content: center;
    align-items: center;
    height: auto;
    margin-left: auto;
}

.join-msg{
    color: #fff;
    text-transform: uppercase;
}

.btn{
    border: 1px solid #fff;
    border-radius: 2px;
    background: none;
    color: #fff;
    height: 35px;
    padding: 0 10px;
    margin-left: 10px;
    text-transform: uppercase;
    cursor: pointer;
}

.join-btn{
    background: #dd0e15;
    border-color: #dd0e15;
}
``` 
######Output
![navbar 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ka5fb8glvc61f8r3ype1.PNG)
Now create movie section.

```HTML
<!-- main section -->
<header class="main">
    <h1 class="heading">movies</h1>
    <p class="info">Movies move us like nothing else can, whether they're scary, funny, dramatic, romantic or anywhere in-between. So many titles, so much to experience.</p>
</header>
```
And style it
```CSS
.main{
    position: relative;
    margin-top: 60px;
    width: 100%;
    padding: 40px 2.5vw;
    color: #fff;
}

.heading{
    text-transform: capitalize;
    font-weight: 900;
    font-size: 50px;
}

.info{
    width: 50%;
    font-size: 20px;
    margin-top: 10px;
}
```
![main-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eb4lpflaqnpynhkos5s1.PNG)
And we have to create a movie list element inside `.main` element, this will hold our same genres movie.

```HTML
<div class="movie-list">

    <button class="pre-btn"><img src="img/pre.png" alt=""></button>

    <h1 class="movie-category">Popular movie</h1>

    <div class="movie-container">
        <div class="movie">
            <img src="img/poster.jpg" alt="">
            <p class="movie-title">movie name</p>
        </div>
    </div>

    <button class="nxt-btn"><img src="img/nxt.png" alt=""></button>

</div>
``` 
You can see here, we have `pre-btn` and `nxt-btn` with them we also have a `movie-card` element. Well, we will create movie card and list element all with JS but for styling purpose we are creating one card here. Just for the sake of CSS.

```CSS
.movie-list{
    width: 100%;
    height: 250px;
    margin-top: 40px;
    position: relative;
}

.movie-category{
    font-size: 20px;
    font-weight: 500;
    margin-bottom: 20px;
    text-transform: capitalize;
}

.movie-container{
    width: 100%;
    height: 200px;
    display: flex;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-behavior: smooth;
}

.movie-container::-webkit-scrollbar{
    display: none;
}

.movie{
    flex: 0 0 auto;
    width: 24%;
    height: 200px;
    text-align: center;
    margin-right: 10px;
    cursor: pointer;
    position: relative;
}

.movie img{
    width: 100%;
    height: 170px;
    object-fit: cover;
}

.movie p{
    text-transform: capitalize;
    height: 20px;
    overflow: hidden;
}

.pre-btn,
.nxt-btn{
    position: absolute;
    height: 200px;
    top: 50%;
    transform: translateY(-50%);
    width: 2.5vw;
    background: #181818;
    border: none;
    outline: none;
    opacity: 0;
}

.pre-btn{
    left: -2.5vw;
}

.nxt-btn{
    right: -2.5vw;
}

.pre-btn img,
.nxt-btn img{
    width: 20px;
    height: 20px;
    object-fit: contain;
}

.nxt-btn:hover,
.pre-btn:hover{
    opacity: 1;
}
```
######Output
![Capture-3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ugy7tq2uyxd819p4pg5c.PNG)

Once we are done styling our cards. we can commit them. 

```HTML
<header class="main">
    <h1 class="heading">movies</h1>
    <p class="info">Movies move us like nothing else can, whether they're scary, funny, dramatic, romantic or anywhere in-between. So many titles, so much to experience.</p>
    <!-- movie list -->
    <!-- <div class="movie-list">

        <button class="pre-btn"><img src="img/pre.png" alt=""></button>

        <h1 class="movie-category">Popular movie</h1>

        <div class="movie-container">
            <div class="movie">
                <img src="img/poster.jpg" alt="">
                <p class="movie-title">movie name</p>
            </div>
        </div>

        <button class="nxt-btn"><img src="img/nxt.png" alt=""></button>

    </div> -->
</header>
```
Our `main` section should look like this. As we are done with homepage.

Now add all JS files in `index.html` file. As we need them now.
```HTML
<script src="js/api.js"></script>
<script src="js/scroll.js"></script>
<script src="js/home.js"></script>
```
>Make sure you add these files in exactly same order.

Now go to [TMDB Official Site](https://www.themoviedb.org/) TO create an API key. If you don't know how to create it. [Watch This](https://youtu.be/FoD33gwhu00?t=1213).

After creating API key paste it into `api.js` file
######api.js
```JS
let api_key = "your api key";
```
And after that go to [TMDB Documentation](https://developers.themoviedb.org/3/getting-started/introduction). And find these three HTTP links.

######api.js
```JS
let api_key = "your api key";

let img_url = "https://image.tmdb.org/t/p/w500";
let genres_list_http = "https://api.themoviedb.org/3/genre/movie/list?";
let movie_genres_http = "https://api.themoviedb.org/3/discover/movie?";
```
1. `img_url` - is to fetch image. Because we'll get movie image's path id. For example if we got image id as `123` then the image url will be `https://image.tmdb.org/t/p/w500/123`
2. `genres_list_http` - is to fetch movie genres list so we don't have to fetch different genres movie manually.
3. `movie_genres_http` - is to fetch the movie having same genres.

After done with these HTTPs. Open `home.js` file.

######home.js
```JS
fetch(genres_list_http + new URLSearchParams({
    api_key: api_key
}))
.then(res => res.json())
.then(data => {
    data.genres.forEach(item => {
        fetchMoviesListByGenres(item.id, item.name);
    })
});
```
######Explanation
Here, we are using `fetch` method to `genres_list_http` that we have declared in `api.js` file. And using `new URLSearchParams` for adding `api_key` parameters to the link. And after getting res we are converting it to JSON be `res.json()` and after converting it to JSON we got the fetched data. Inside that. before understanding what we are doing. First see our fetched data structure.

![Capture-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6zb67ji867h6op4ggo7.PNG)

So as to understood the data structure. Now understand what we are doing after getting JSON data. 
```JS
data.genres.forEach(item => {
    fetchMoviesListByGenres(item.id, item.name);
})
```
As we have an array of genres, we are looping through each and every genres using `forEach` method. And inside that we are calling `fetchMoviesListByGenres(id, genres)` which we'll create next. 

Now fetch movies with genres.

```JS
const fetchMoviesListByGenres = (id, genres) => {
    fetch(movie_genres_http + new URLSearchParams({
        api_key: api_key,
        with_genres: id,
        page: Math.floor(Math.random() * 3) + 1
    }))
    .then(res => res.json())
    .then(data => {
        makeCategoryElement(`${genres}_movies`, data.results);
    })
    .catch(err =>  console.log(err));
}
```
######Explanation
Here we are doing the same, we are fetching data but in this case we are making request to `movie_genres_http` and adding some more parameters. 
`with_genres` param will give us movie with only that genres for instance if our genres id if for comedy movies, then we'll only get comedy movies.
`page` param will give use what of the result we want and in this case we are using `Math.random()` to fetch some random page of movie result.

After getting the data, we are performing the same `res.json()` to covert it into JSON. And calling `makeCategoryElement(category, data)` which will create our movie categories. Same if you want you can console log the data structure.

Now create movie categories. But before that select our `main` element from HTML.
```JS
const main = document.querySelector('.main');
```

```JS
const makeCategoryElement = (category, data) => {
    main.innerHTML += `
    <div class="movie-list">

        <button class="pre-btn"><img src="img/pre.png" alt=""></button>

        <h1 class="movie-category">${category.split("_").join(" ")}</h1>

        <div class="movie-container" id="${category}">

        </div>

        <button class="nxt-btn"><img src="img/nxt.png" alt=""></button>

    </div>
    `;
    makeCards(category, data);
}
```
######Explanation
In this function, we have two arguments one is `category` and second is `data`. So the first thing our function is doing is adding a `.movie-list` element to our `main` element using `innerHTML`. If you remember this we created in our HTML file but at last commented copy that code and paste it here. Make sure you use `+=` not `=` because we don't want to re-write its HTML.

`<h1 class="movie-category">${category.split("_").join(" ")}</h1>`
if you see this line. First of all we are using JS template string if you don;t use that you'll be not able to write like this. So here as we had an `h1` element. we are setting it's text to our category that we got at the start of the function. But we also performing some methods here.Let's see them in detail.

for instance, assume category is equal to comedy.

1. `<h1 class="movie-category">${category}</h1>`
Then output will be - comdey_movies. But we don't wont `_` that why we split it.
2. `<h1 class="movie-category">${category.split("_")}</h1>`
Then it will not work because now we have an array ["comedy", "movies"]. That's why use `join` method to join the array.
3. `<h1 class="movie-category">${category.split("_").join(" ")}</h1>`
Then the output will be - Comedy Movies

I hope you understood this.

And then we are setting up a unique id to `movie-container` element so we can add card to it later. And at the very last, we are calling `makeCards(category, data)` to make cards inside that movie container element.

Now create a cards.

```JS
const makeCards = (id, data) => {
    const movieContainer = document.getElementById(id);
    data.forEach((item, i) => {
        
    })
}
```
######Explanation
Inside this function, we are selecting the movie container element on the start using that `id` we got from the above function. And after that we are looping through `data` using `forEach` method. Inside that We are checking some condition.
```JS
if(item.backdrop_path == null){
   item.backdrop_path = item.poster_path;
   if(item.backdrop_path == null){
      return;
  }
}
```
This condition is checking, if we don't have movie `backdrop` image path in our result set it to `poster_path` and we don't have that too. Don't make the card. Sometime TMDB movie's data do not have image path in it that's why we are checking for it.

After that we have
```JS
movieContainer.innerHTML += `
<div class="movie" onclick="location.href = '/${item.id}'">
    <img src="${img_url}${item.backdrop_path}" alt="">
    <p class="movie-title">${item.title}</p>
</div>
`;
```
Here, we are using the `innerHTML` method to append the card HTML structure that we already made at the start. And again here also we are using template strings. If you see we have `onclick` event to `movie-card` element which, in that event we are using `location.href` to redirect user to movie page that we'll create next.

```JS
if(i == data.length - 1){
    setTimeout(() => {
        setupScrolling();
    }, 100);
}
```
And this is checking for the last cast. when we are done creating cards. we are running `setupScrolling()` function to setup slider effect. We also have to create this.

After writing this much of JS. Now we can see the output without any errors.

######Output
![Capture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rntfwfxvpbgc5qghyzel.PNG)

But we haven't created our slider effect write. For that open `scroll.js` file.

######scroll.js
```JS
const setupScrolling = () => {
    const conainter = [...document.querySelectorAll('.movie-container')];
    const nxtBtn = [...document.querySelectorAll('.nxt-btn')];
    const preBtn = [...document.querySelectorAll('.pre-btn')];
}
```
######Explanation
First in this function we are selecting our containers, next buttons and previous buttons using `querySelectorAll` method.

After selecting them. Inside the function type this.

```JS
conainter.forEach((item, i) => {
    let containerDimensions = item.getBoundingClientRect();
    let containerWidth = containerDimensions.width;
})
```
Here we are looping through each container element. And using `getBoundingClientRect` method to get container's dimensions. And at last storing `containerDimensions.width` (which of course give container width) to `containerWidth`.

After that inside this for loop add this.
```JS
nxtBtn[i].addEventListener('click', () => {
    item.scrollLeft += containerWidth;
})

preBtn[i].addEventListener('click', () => {
    item.scrollLeft -= containerWidth;
}
```
Here we are selecting our `nxtBtn` and `preBtn` with container's index. And adding click event to them. And just performing simple maths.

After this we should be able to get our slider effect.

Our Home page is done.

###Server.js
Now for about page we need to add some more codes in `server.js`.
Type this before `app.listen()`;
```JS
app.get('/:id', (req, res) => {
    res.sendFile(path.join(initial_path, "about.html"));
})

app.use((req, res) => {
    res.json("404");
})
```
Here, we are adding  GET request listener to `/:id` path. THis means anything with a single slash in front, execute the code. It will work for `/123` but not for `/123/12/1`. And at last we have `app.use()` which again use as a middle ware and this means that if the requesting path is not the same as above paths. Execute this. Means `404` message.

After this you'll be able to redirect yourself to movie detail page by clicking on movie card.

###About Page

Let's create this last page. For this link both `about.css` and `style.css` file so we don't have to write lot of CSS.

And copy paste the navbar here. After that create movie-info element
######about.html
```HTML
<!-- movie info -->
<div class="movie-info">
    <div class="movie-detail">
        <h1 class="movie-name">Movie Name</h1>
        <p class="genres">Comedy</p>
        <p class="des">Lorem ipsum dolor sit amet consectetur, adipisicing elit. In commodi incidunt odit inventore suscipit, debitis officia modi exercitationem animi nemo.</p>
        <p class="starring"><span>Starring:</span></p>
    </div>
</div>
```
And style it.
```CSS
.movie-info{
    width: 100%;
    height: calc(100vh - 60px);
    margin-top: 60px;
    background-size: cover;
    background-repeat: no-repeat;
}

.movie-detail{
    width: 50%;
    height: 100%;
    background: rgb(24, 24, 24);
    background: linear-gradient(90deg, rgba(24, 24, 24, 1), rgba(24, 24, 24, 0) 100%);
    padding: 5vw;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    color: #fff;
}

.movie-name{
    font-size: 30px;
    font-weight: 500;
}

.genres{
    opacity: 0.6;
    margin: 30px 0;
}

.des{
    width: 70%;
    line-height: 20px;
    margin-bottom: 30px;
}

.starring span{
    opacity: 0.6;
}
```
######Output
![Capture-4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2kr5320lrqqngpu260g.PNG)
 Once CSS is complete you can remove all the text from the info elements making them totally empty.
```HTML
<h1 class="movie-name"></h1>
<p class="genres"></p>
<p class="des"></p>
<p class="starring"><span>Starring:</span></p>
```
Like this.

Now create video recommendation.

```HTML
<div class="trailer-container">
    <h1 class="heading">Video Clip</h1>
    <iframe src="" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
```
You can notice we have `iframe` here. And this is little hard to understand so I suggest you [watch this](https://youtu.be/FoD33gwhu00?t=2535) to understand video trailer better.
Style It.
```CSS
.trailer-container,
.recommendations{
    color: #fff;
    padding: 5vw 5vw 0;
}

.heading{
    font-size: 30px;
    font-weight: 300;
    margin-bottom: 20px;
}

iframe{
    width: 400px;
    height: 200px;
}
```
In output we'll see nothing except our movie info element and a video clip text. Because our `iframe` source is empty.

Now create recommendation container.

```HTML
<div class="recommendations">
    <h1 class="heading">More Like This</h1>
    <div class="recommendations-container">
        <div class="movie">
            <img src="img/poster.jpg" alt="">
            <p class="movie-title">movie name</p>
        </div>
    </div>
</div>
```
CSS
```CSS
.recommendations-container{
    width: 100%;
    display: flex;
    flex-wrap: wrap;
}

.movie p{
    position: absolute;
    bottom: 30px;
    width: 100%;
    height: 30px;
    line-height: 30px;
    background: rgba(0, 0, 0, 0.5);
    text-align: center;
    opacity: 0;
}

.movie:hover p{
    opacity: 1;
}
```
######Output
![Capture05](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpwkhuy13llp4etlgvtc.PNG)
As we have done styling. You can comment `.movie` element. This is the same element that we have created in home page.

Add scripts to this page also. And remeber to add this is same exact order.
```JS
<script src="js/api.js"></script>
<script src="js/about.js"></script>
```

Now open `api.js` file. And add this.
```JS
let original_img_url = "https://image.tmdb.org/t/p/original";
let movie_detail_http = "https://api.themoviedb.org/3/movie";
```
You can find these HTTPs from TMDB documentation. 
`original_img_url` - This is to fetch movie image in original resolution.
`movie_detail_http` - This is to fetch details of a particular movie.

Now open `about.js`. And write this.
```JS
let movie_id = location.pathname;
```
by `location.pathname` you will be able to extract movie id from the URL. For example if the URL is `localhost:3000/123` then this will return `/123` which is our movie id.

After that fetch movie details using the same `fetch` method. and pass the fetched data to a function called `setupMovieInfo(data)`.
```JS
// fetching movie details
fetch(`${movie_detail_http}${movie_id}?` + new URLSearchParams({
    api_key: api_key
}))
.then(res => res.json())
.then(data => {
    setupMovieInfo(data);
})
```
Let's create `setupMovieInfo`.

```JS
const setupMovieInfo = (data) => {
    const movieName = document.querySelector('.movie-name');
    const genres = document.querySelector('.genres');
    const des = document.querySelector('.des');
    const title = document.querySelector('title');
    const backdrop = document.querySelector('.movie-info');

    title.innerHTML = movieName.innerHTML = data.title; 
    genres.innerHTML = `${data.release_date.split('-')[0]} | `;
    for(let i = 0; i < data.genres.length; i++){
        genres.innerHTML += data.genres[i].name + formatString(i, data.genres.length);
    }

    if(data.adult == true){
        genres.innerHTML += ' | +18';
    }

    if(data.backdrop_path == null){
        data.backdrop_path = data.poster_path;
    }

    des.innerHTML = data.overview.substring(0, 200) + '...';

    backdrop.style.backgroundImage = `url(${original_img_url}${data.backdrop_path})`;
}
```
######Explanation
This function is very simple, at start it is selecting all elements like movie name, title tag, des, genres. And after selecting all the elements. We are setting the value using `innerHTML` method. But for genres we have some conditions, like at first we are adding only released year by doing some formatting. And after that we are loopin through all the genres movie's data have and adding them to the genres with some formatting. And yes, you can see `formatString` function let's create this.
```JS
const formatString = (currentIndex, maxIndex) => {
    return (currentIndex == maxIndex - 1) ? '' : ', ';
}
```
After genres we are checking for `backdrop_path` as we checked it before in homepage. And setting up the image as a background image.

Then as we don't get the cast info with the movies detail. We have to fetch it seperately.

```JS
//fetching cast info

fetch(`${movie_detail_http}${movie_id}/credits?` + new URLSearchParams({
    api_key: api_key
}))
.then(res => res.json())
.then(data => {
    const cast = document.querySelector('.starring');
    for(let i = 0; i < 5; i++){
        cast.innerHTML += data.cast[i].name + formatString(i, 5);
    }
})
```
And I think this is very easy to understand. But if you have a doubt ask me in discussions.

Now if we see the output.

######Output
![Capture-2 (1)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvuxqs3lyqdw5zmatl97.png)

Now let's fetch video clips.

```JS
/ fetching video clips

fetch(`${movie_detail_http}${movie_id}/videos?` + new URLSearchParams({
    api_key: api_key
}))
.then(res => res.json())
.then(data => {
    let trailerContainer = document.querySelector('.trailer-container');

    let maxClips = (data.results.length > 4) ? 4 : data.results.length;

    for(let i = 0; i < maxClips; i++){
        trailerContainer.innerHTML += `
        <iframe src="https://youtube.com/embed/${data.results[i].key}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        `;
    }
})
```
Here, we are fetching videos detail related to movies. And after getting results we are checking a condition to set `maxClips` because we want 4 clips at most. And after that we are looping `maxClips` time. And creating an `Iframe` this is the same structure that we have in our HTML file. Copy that from there to here. But notice it's `src` attribute carefully.

######Output
![Capture-3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4rqc0cejgvfwomdqfp1.PNG)
 
Now the last thing create recommendations.

```JS
// fetch recommendations

fetch(`${movie_detail_http}${movie_id}/recommendations?` + new URLSearchParams({
    api_key: api_key
}))
.then(res => res.json())
.then(data => {
    let container = document.querySelector('.recommendations-container');
    for(let i = 0; i < 16; i++){
        if(data.results[i].backdrop_path == null){
            i++;
        }
        container.innerHTML += `
        <div class="movie" onclick="location.href = '/${data.results[i].id}'">
            <img src="${img_url}${data.results[i].backdrop_path}" alt="">
            <p class="movie-title">${data.results[i].title}</p>
        </div>
        `;
    }
})
```
And at the last step of the project. We are fetching similar movies like that from TMDB. And, after getting the data we are making only 16 cards. This is very similar to what we did for creating card in `home.js`.

######Output
![Capture-4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6gu1rwu375cvsohb0kkt.PNG)
 
We are done.

So, that's it. I hope you understood each and everything. If you have doubt or I missed some thing let me know in the comments.

#Articles you may found Useful

1. [Infinte CSS loader](https://dev.to/kunaal438/quick-css-make-infinity-loading-animation-for-your-next-website-187k)
2. [Best CSS Effect](https://dev.to/kunaal438/css-the-best-css-effects-of-all-time-most-underrated-web-ux-2chj)
3. [Wave Button Hover Effect](https://dev.to/kunaal438/create-awesome-wavy-button-hover-effect-pure-css-wavy-design-1722)
4. [Youtube API - Youtube Clone](https://dev.to/kunaal438/create-working-youtube-clone-with-search-box-youtube-api-2a6e)
5. [Gradient Checkbox](https://dev.to/kunaal438/checkbox-css-style-gradient-checkbox-with-pure-css-custom-input-css-3gko)

I really appreciate if you can subscribe my youtube channel. I create awesome web contents. [Subscribe](https://www.youtube.com/c/modern_web?sub_confirmation=1)

[Source Code](https://github.com/kunaal438/netflix-clone-2.0)

Thanks For reading.