Create A YouTube Homepage Clone in ReactJS and Tailwind CSS
Tags: react, tailwindcss, javascript, coding
Published: 2024-06-13 09:58:08

Creating a clone of the YouTube homepage can be both enjoyable and helpful for enhancing your front-end development skills. This project offers a chance to work on a familiar design while getting practical experience with commonly used tools like [React.js](https://react.dev/) and [Tailwind CSS](https://tailwindcss.com/). It also helps you understand how modern web applications are structured and styled.

In this blog post, I’ll guide you through the process of creating a responsive YouTube homepage clone using React.js and Tailwind CSS. This project will replicate key features of YouTube’s design, such as a [navbar](https://www.codingnepalweb.com/category/navigation-bar/) with search, a grid layout for videos, a collapsible [sidebar](https://www.codingnepalweb.com/category/sidebar-menu/), and options for dark or light themes.

## Demo of YouTube Homepage Clone in React.js & Tailwind
{% embed https://www.youtube.com/watch?v=EXXFDliZ9u0 %}

## Tools and Libraries

- **React.js:** Used for building the user interface.
- **Tailwind CSS:** Used for styling the components.
- **Lucide React:** Used for icons in the sidebar and other components.

## Setting Up the Project

Before we start making YouTube homepage clone with React.js and Tailwind CSS, make sure you have Node.js installed on your computer. If you don’t have it, you can download and install it from the official [Node.js](https://nodejs.org/en/download/prebuilt-installer) website.

After installing Node.js, follow these easy steps to set up your project:

**Create a Project Folder**

- Make a new folder, for instance, “youtube-homepage-clone”.
- Open this folder in your VS Code editor.

**Initialize the Project**
Use [Vite](https://vitejs.dev/) to create a new React app with this command:

```sql
npm create vite@latest ./ -- --template react
```
Install necessary dependencies:

```c#
npm install
```
**Install Tailwind CSS**

Install Tailwind CSS, PostCSS, and Autoprefixer:

```c#
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```
**Install Lucide React**

Add icons with Lucide React:

```c#
npm install lucide-react
```
**Configure Tailwind CSS**

Replace the code in `tailwind.config.js` with the provided configuration.

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  darkMode: "class",
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};
```
**Modify CSS Files**

- Remove the default `App.css` file.
- Replace the content of `index.css` with the provided code.

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

.custom_scrollbar {
  scrollbar-color: #999 transparent;
}

aside.custom_scrollbar {
  scrollbar-width: none;
  scrollbar-gutter: stable;
}

aside.custom_scrollbar:hover {
  scrollbar-width: thin;
}

.no_scrollbar::-webkit-scrollbar {
  display: none;
}

.no_scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
```
**Assets Folder**

Download the [assets](https://www.codingnepalweb.com/custom-projects/youtube-homepage-clone-reactjs-assets.zip) folder and replace the existing one in your project directory. This folder contains the logo and user image used on this YouTube homepage project.

**Start the Development Server**

To view your project in the browser, start the development server by running:

```
npm run dev
```

## Creating the Components
Within the **src** directory of your project, organize your files by creating three different folders: _“layouts”_, _“components”_, and _“constants”_. Inside these folders, create the following files:

- layouts/Navbar.jsx
- layouts/Sidebar.jsx
- components/CategoryPill.jsx
- components/VideoItem.jsx
- constants/index.js

## Adding the Codes
Add the respective code to each newly created file. These files define the layout, functionality, and constants used in the website.

In `layouts/Navbar.jsx`, add the following code. This file defines the layout for the navigation bar of our application.

```javascript
import { ArrowLeft, Menu, Mic, MoonStar, Search, Sun } from "lucide-react";
import Logo from "../assets/logo.png";
import UserImg from "../assets/user.jpg";
import { useState } from "react";

const Navbar = ({ toggleSidebar }) => {
  // State for dark mode and search box visibility
  const [isDarkMode, setIsDarkMode] = useState(false);
  const [isShowSearchBox, setIsShowSearchBox] = useState(false);

  // Toggles the search box visibility
  const toggleSearchBox = () => {
    setIsShowSearchBox(!isShowSearchBox);
  };

  // Toggles dark mode and updates the document body class
  const toggleDarkMode = () => {
    setIsDarkMode(!isDarkMode);
    document.body.classList.toggle("dark");
  };

  return (
    <header className="sticky top-0 z-10 bg-white dark:bg-neutral-900">
      <nav className="py-2 pb-5 px-4 max-md:px-3 flex items-center justify-between">
        <HeaderLeftSection
          toggleSidebar={toggleSidebar}
          isShowSearchBox={isShowSearchBox}
        />
        <div
          className={`flex gap-3 h-10 flex-grow max-w-[600px] max-lg:max-w-[400px] ${isShowSearchBox && "max-md:max-w-full"}`}
        >
          <button
            onClick={toggleSearchBox}
            className={`p-2 mr-3 h-full w-10 rounded-full bg-neutral-100 md:hidden ${!isShowSearchBox && "max-md:hidden"} hover:bg-neutral-200 dark:bg-neutral-800 dark:border-neutral-500 hover:dark:bg-neutral-700`}
          >
            <ArrowLeft className="dark:text-neutral-400" />
          </button>
          <div className={`flex w-full ${!isShowSearchBox && "max-md:hidden"}`}>
            <input
              className="border border-neutral-300 w-full h-full rounded-l-full px-4 outline-none focus:border-blue-500 dark:bg-neutral-900 dark:border-neutral-500 dark:focus:border-blue-500 dark:text-neutral-300"
              type="search"
              placeholder="Search"
            />
            <button className="border border-neutral-300 border-l-0 px-5 rounded-r-full hover:bg-neutral-100 dark:border-neutral-500 hover:dark:bg-neutral-700">
              <Search className="dark:text-neutral-400" />
            </button>
          </div>
          <button
            className={`max-md:hidden p-2 h-full w-10 rounded-full bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-800 dark:border-neutral-500 hover:dark:bg-neutral-700`}
          >
            <Mic className="dark:text-neutral-400" />
          </button>
        </div>
        <div
          className={`flex items-center gap-4 ${isShowSearchBox && "max-md:hidden"}`}
        >
          <button
            onClick={toggleSearchBox}
            className={`p-2 md:hidden rounded-full hover:bg-neutral-200 dark:border-neutral-500 hover:dark:bg-neutral-700`}
          >
            <Search className="dark:text-neutral-400" />
          </button>
          <button
            onClick={toggleDarkMode}
            className="p-2 rounded-full hover:bg-neutral-200 dark:border-neutral-500 hover:dark:bg-neutral-700"
          >
            {isDarkMode ? (
              <Sun className="dark:text-neutral-400" />
            ) : (
              <MoonStar className="dark:text-neutral-400" />
            )}
          </button>
          <button>
            <img
              className="w-8 h-8 rounded-full"
              src={UserImg}
              alt="User Image"
            />
          </button>
        </div>
      </nav>
    </header>
  );
};

// Component for the menu toggler and logo
export const HeaderLeftSection = ({ toggleSidebar, isShowSearchBox }) => {
  return (
    <div
      className={`flex gap-4 items-center ${isShowSearchBox && "max-md:hidden"}`}
    >
      <button
        onClick={toggleSidebar}
        className="p-2 rounded-full hover:bg-neutral-200 hover:dark:bg-neutral-700"
      >
        <Menu className="dark:text-neutral-400" />
      </button>
      <a href="#" className="flex items-center gap-2 dark:text-neutral-300">
        <img className="w-8" src={Logo} alt="Logo" />
        <h2 className="text-xl font-bold ">CnTube</h2>
      </a>
    </div>
  );
};

export default Navbar;
```
In `layouts/Sidebar.jsx`, add the following code. This file defines the layout for the sidebar bar of our application.

```javascript
import { sidebarLinks } from "../constants";
import {
  Home,
  Video,
  ListVideo,
  User,
  History,
  Flame,
  Music,
  Gamepad2,
  Trophy,
  Youtube,
  CirclePlay,
  Blocks,
  Settings,
  Flag,
  CircleHelp,
  MessageSquareWarning,
} from "lucide-react";

const iconComponents = {
  Home,
  Video,
  ListVideo,
  User,
  History,
  Flame,
  Music,
  Gamepad2,
  Trophy,
  Youtube,
  CirclePlay,
  Blocks,
  Settings,
  Flag,
  CircleHelp,
  MessageSquareWarning,
};
import { HeaderLeftSection } from "./Navbar";
import React from "react";

// Sidebar component with conditional styling based on isSidebarOpen prop
const Sidebar = ({ isSidebarOpen, toggleSidebar }) => {
  return (
    <aside
      className={`
      ${
        isSidebarOpen
          ? "max-lg:left-0 w-64 px-3 max-md:px-2"
          : "max-lg:left-[-100%] w-0 px-0"
      } 
      max-lg:absolute max-lg:h-screen max-lg:top-0 pb-5 z-20 bg-white mb-2 overflow-y-auto  custom_scrollbar dark:bg-neutral-900
    `}
    >
      <div className="lg:hidden pb-4 pt-2 px-1 sticky top-0 bg-white dark:bg-neutral-900">
        <HeaderLeftSection toggleSidebar={toggleSidebar} />
      </div>

      {sidebarLinks.map((category, catIndex) => (
        <div key={catIndex}>
          <h4
            className={`text-base font-medium mb-2 ml-2 ${category.categoryTitle && "mt-4"} whitespace-nowrap overflow-hidden text-ellipsis dark:text-neutral-300`}
          >
            {category.categoryTitle}
          </h4>
          {category.links.map((link, index) => {
            const IconComponent = iconComponents[link.icon];
            return (
              <React.Fragment key={`${catIndex}-${index}`}>
                <Link link={link} IconComponent={IconComponent} />
                {index === category.links.length - 1 &&
                  catIndex !== sidebarLinks.length - 1 && (
                    <div className="h-[1px] w-full bg-neutral-200 dark:bg-neutral-700"></div>
                  )}
              </React.Fragment>
            );
          })}
        </div>
      ))}
    </aside>
  );
};

// Link component for each sidebar link
export const Link = ({ link, IconComponent }) => {
  return (
    <a
      href={link.url}
      className={`flex items-center py-2 px-3 rounded-lg  hover:bg-neutral-200 mb-2 whitespace-nowrap overflow-hidden text-ellipsis dark:text-neutral-300 dark:hover:bg-neutral-500`}
    >
      {IconComponent && <IconComponent className="mr-2 h-5 w-5" />}
      {link.title}
    </a>
  );
};

export default Sidebar;
```
In `components/CategoryPill.jsx`, add the following code. This component code is used for rendering category pills.

```javascript
import React from "react";

const CategoryPill = ({ category }) => {
  return (
    <button
      className={`whitespace-nowrap rounded-lg px-3 py-1 ${category === "All" ? "bg-black text-white hover:bg-black dark:bg-white dark:text-neutral-950 dark:hover:bg-white" : "bg-neutral-200"} hover:bg-neutral-300 dark:bg-neutral-700 dark:hover:bg-neutral-600  dark:text-neutral-300`}
    >
      {category}
    </button>
  );
};

export default CategoryPill;
```
In `components/VideoItem.jsx`, add the following code. This component handles the rendering of individual video items within our application.

```javascript
const VideoItem = ({ video }) => {
  return (
    <a className="group" href="#">
      <div className="relative rounded-lg overflow-hidden">
        <img
          className="rounded-lg aspect-video"
          src={video.thumbnailURL}
          alt="Video Thumbnail"
        />
        <p className="absolute bottom-2 right-2 text-sm bg-black bg-opacity-50 text-white px-1.5 font-medium rounded-md">
          {video.duration}
        </p>
      </div>
      <div className="flex gap-3 py-3 px-2">
        <img
          className="h-9 w-9 rounded-full"
          src={video.channel.logo}
          alt={video.channel.name}
        />
        <div>
          <h2 className="group-hover:text-blue-500 font-semibold leading-snug dark:text-neutral-300">
            {video.title}
          </h2>
          <p className="text-sm mt-1 text-neutral-700 hover:text-neutral-500 dark:text-neutral-300">
            {video.channel.name}
          </p>
          <p className="text-sm text-neutral-700 dark:text-neutral-300">
            {video.views} Views • {video.postedAt}
          </p>
        </div>
      </div>
    </a>
  );
};

export default VideoItem;
```
In `constants/index.js`, include the following code. This file serves as a main location for defining and managing constants used throughout the website, ensuring consistency and maintainability.

```javascript
export const categories = [
  "All",
  "Website",
  "Music",
  "Gaming",
  "Node.js",
  "React.js",
  "TypeScript",
  "Coding",
  "Data analysis",
  "JavaScript",
  "Web design",
  "Tailwind",
  "HTML",
  "CSS",
  "Next.js",
  "Express.js",
];

export const sidebarLinks = [
  {
    categoryTitle: "",
    links: [
      {
        icon: "Home",
        title: "Home",
        url: "#",
      },
      {
        icon: "Video",
        title: "Shorts",
        url: "#",
      },
      {
        icon: "ListVideo",
        title: "Subscription",
        url: "#",
      },
    ],
  },
  {
    categoryTitle: "",
    links: [
      {
        icon: "User",
        title: "You",
        url: "#",
      },
      {
        icon: "History",
        title: "History",
        url: "#",
      },
    ],
  },
  {
    categoryTitle: "Explore",
    links: [
      {
        icon: "Flame",
        title: "Trending",
        url: "#",
      },
      {
        icon: "Music",
        title: "Shorts",
        url: "#",
      },
      {
        icon: "Gamepad2",
        title: "Gaming",
        url: "#",
      },
      {
        icon: "Trophy",
        title: "Sports",
        url: "#",
      },
    ],
  },
  {
    categoryTitle: "More from YouTube",
    links: [
      {
        icon: "Youtube",
        title: "YouTube Pro",
        url: "#",
      },
      {
        icon: "CirclePlay",
        title: "YouTube Music",
        url: "#",
      },
      {
        icon: "Blocks",
        title: "YouTube Kids",
        url: "#",
      },
    ],
  },
  {
    categoryTitle: "",
    links: [
      {
        icon: "Settings",
        title: "Settings",
        url: "#",
      },
      {
        icon: "Flag",
        title: "Report",
        url: "#",
      },
      {
        icon: "CircleHelp",
        title: "Help",
        url: "#",
      },
      {
        icon: "MessageSquareWarning",
        title: "Feedback",
        url: "#",
      },
    ],
  },
];

export const videos = [
  {
    id: "3",
    title: "Top 10 Easy To Create JavaScript Games For Beginners",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "27K",
    postedAt: "4 months ago",
    duration: "10:03",
    thumbnailURL: "https://i.ytimg.com/vi/OORUHkgg4IM/maxresdefault.jpg",
    videoURL: "https://youtu.be/OORUHkgg4IM",
  },
  {
    id: "2",
    title: "Create Responsive Website with Login & Registration Form",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "68K",
    postedAt: "9 months ago",
    duration: "29:43",
    thumbnailURL: "https://i.ytimg.com/vi/YEloDYy3DTg/maxresdefault.jpg",
    videoURL: "https://youtu.be/YEloDYy3DTg",
  },
  {
    id: "7",
    title: "Create a Responsive Calculator in HTML CSS & JavaScript",
    channel: {
      name: "CodingLab",
      url: "https://www.youtube.com/@CodingLabYT",
      logo: "https://yt3.googleusercontent.com/uITV5E7auiZMDD_BwhVRJMHXXY6qQc0GqBgVyP5LWYTmeRlUP2Dc945UlIbODvztd96ReOts=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "30K",
    postedAt: "2 year ago",
    duration: "11:13",
    thumbnailURL: "https://i.ytimg.com/vi/cHkN82X3KNU/maxresdefault.jpg",
    videoURL: "https://youtu.be/cHkN82X3KNU",
  },
  {
    id: "9",
    title: "Responsive Admin Dashboard Panel in HTML CSS & JavaScript",
    channel: {
      name: "CodingLab",
      url: "https://www.youtube.com/@CodingLabYT",
      logo: "https://yt3.googleusercontent.com/uITV5E7auiZMDD_BwhVRJMHXXY6qQc0GqBgVyP5LWYTmeRlUP2Dc945UlIbODvztd96ReOts=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "161K",
    postedAt: "1 year ago",
    duration: "1:37:13",
    thumbnailURL: "https://i.ytimg.com/vi/AyV954yKRSw/maxresdefault.jpg",
    videoURL: "https://youtu.be/AyV954yKRSw",
  },
  {
    id: "4",
    title: "Create Text Typing Effect in HTML CSS & Vanilla JavaScript",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "17K",
    postedAt: "10 months ago",
    duration: "9:27",
    thumbnailURL: "https://i.ytimg.com/vi/DLs1X9T1GcY/maxresdefault.jpg",
    videoURL: "https://youtu.be/DLs1X9T1GcY",
  },
  {
    id: "1",
    title: "Multiple File Uploading in HTML CSS & JavaScript",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "7.4K",
    postedAt: "3 weeks ago",
    duration: "30:20",
    thumbnailURL: "https://i.ytimg.com/vi/_RSaI2CxlXU/maxresdefault.jpg",
    videoURL: "https://youtu.be/_RSaI2CxlXU",
  },
  {
    id: "5",
    title: "How to Make Chrome Extension in HTML CSS & JavaScript",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "24K",
    postedAt: "1 year ago",
    duration: "19:27",
    thumbnailURL: "https://i.ytimg.com/vi/coj-l7IrwGU/maxresdefault.jpg",
    videoURL: "https://youtu.be/coj-l7IrwGU",
  },
  {
    id: "8",
    title: "How to make Responsive Image Slider in HTML CSS & JavaScript",
    channel: {
      name: "CodingLab",
      url: "https://www.youtube.com/@CodingLabYT",
      logo: "https://yt3.googleusercontent.com/uITV5E7auiZMDD_BwhVRJMHXXY6qQc0GqBgVyP5LWYTmeRlUP2Dc945UlIbODvztd96ReOts=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "1M",
    postedAt: "1 year ago",
    duration: "37:13",
    thumbnailURL: "https://i.ytimg.com/vi/q4RgxiDM6v0/maxresdefault.jpg",
    videoURL: "https://youtu.be/q4RgxiDM6v0",
  },
  {
    id: "6",
    title: "How to make Responsive Card Slider in HTML CSS & JavaScript",
    channel: {
      name: "CodingLab",
      url: "https://www.youtube.com/@CodingLabYT",
      logo: "https://yt3.googleusercontent.com/uITV5E7auiZMDD_BwhVRJMHXXY6qQc0GqBgVyP5LWYTmeRlUP2Dc945UlIbODvztd96ReOts=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "42K",
    postedAt: "1 year ago",
    duration: "23:45",
    thumbnailURL: "https://i.ytimg.com/vi/qOO6lVMhmGc/maxresdefault.jpg",
    videoURL: "https://youtu.be/qOO6lVMhmGc",
  },
  {
    id: "11",
    title: "Flipping Card UI Design in HTML & CSS",
    channel: {
      name: "CodingLab",
      url: "https://www.youtube.com/@CodingLabYT",
      logo: "https://yt3.googleusercontent.com/uITV5E7auiZMDD_BwhVRJMHXXY6qQc0GqBgVyP5LWYTmeRlUP2Dc945UlIbODvztd96ReOts=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "85K",
    postedAt: "2 months ago",
    duration: "12:24",
    thumbnailURL: "https://i.ytimg.com/vi/20Qb7pNMv-4/maxresdefault.jpg",
    videoURL: "https://youtu.be/20Qb7pNMv-4",
  },
  {
    id: "13",
    title: "How To Create A Responsive Website Using HTML & CSS",
    channel: {
      name: "MicroCoding",
      url: "https://www.youtube.com/@MicroCoding.",
      logo: "https://yt3.googleusercontent.com/pz6ex8LxSI-8A4S-sFNZl3QylmXToJWwD7z5zXP-IdSIfFTWPMXCGf8fxKjhEs3CwYBe-S2gzM8=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "7.2K",
    postedAt: "2 weeks ago",
    duration: "1:18:24",
    thumbnailURL: "https://i.ytimg.com/vi/tECCCaErjtM/maxresdefault.jpg",
    videoURL: "https://youtu.be/tECCCaErjtM",
  },
  {
    id: "15",
    title: "Create Text Typing Effect in HTML CSS & Vanilla JavaScript",
    channel: {
      name: "CodingNepal",
      url: "https://www.youtube.com/@CodingNepal",
      logo: "https://yt3.googleusercontent.com/VYLLrblIs_umHCFyK_-q5HJLfB-aDc5ax94uUjNaU5IQXZAlMn6bMVPG-AaLR3-k5_HcBMcI6MA=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "17K",
    postedAt: "10 months ago",
    duration: "9:27",
    thumbnailURL: "https://i.ytimg.com/vi/DLs1X9T1GcY/maxresdefault.jpg",
    videoURL: "https://youtu.be/DLs1X9T1GcY",
  },
  {
    id: "12",
    title: "Beautiful Login Form using HTML & CSS only",
    channel: {
      name: "MicroCoding",
      url: "https://www.youtube.com/@MicroCoding.",
      logo: "https://yt3.googleusercontent.com/pz6ex8LxSI-8A4S-sFNZl3QylmXToJWwD7z5zXP-IdSIfFTWPMXCGf8fxKjhEs3CwYBe-S2gzM8=s176-c-k-c0x00ffffff-no-rj",
    },
    views: "4.2K",
    postedAt: "4 days ago",
    duration: "18:24",
    thumbnailURL: "https://i.ytimg.com/vi/jkThO1GIP9Y/maxresdefault.jpg",
    videoURL: "https://youtu.be/jkThO1GIP9Y",
  },
];
```
Replace the content of `src/App.jsx` with the provided code. It imports and renders the necessary components, such as the Navbar and Sidebar, to create a layout resembling the YouTube homepage.

```javascript
import Navbar from "./layouts/Navbar";
import { categories, videos } from "./constants";
import VideoItem from "./components/VideoItem";
import CategoryPill from "./components/CategoryPill";
import Sidebar from "./layouts/Sidebar";
import { useEffect, useState } from "react";

const App = () => {
  // State to control sidebar visibility
  const [isSidebarOpen, setIsSidebarOpen] = useState(true);

  // Hide sidebar on mobile by default
  useEffect(() => {
    if (window.innerWidth <= 1024) {
      setIsSidebarOpen(false);
    }
  }, []);

  // Toggle the sidebar visibility
  const toggleSidebar = () => {
    setIsSidebarOpen(!isSidebarOpen);
  };

  return (
    <div className="max-h-screen flex flex-col dark:bg-neutral-900">
      <Navbar toggleSidebar={toggleSidebar} />
      <div className="flex overflow-auto">
        <Sidebar toggleSidebar={toggleSidebar} isSidebarOpen={isSidebarOpen} />
        <div className="w-full px-4 max-md:px-3 pl-7 overflow-x-hidden custom_scrollbar">
          <div className="flex w-full gap-3 overflow-x-auto no_scrollbar pb-3 sticky top-0 z-10 bg-white dark:bg-neutral-900">
            {/* Mapping through categories to render a CategoryPill for each */}
            {categories.map((category) => (
              <CategoryPill key={category} category={category} />
            ))}
          </div>
          <div className="grid gap-4 grid-cols-[repeat(auto-fill,minmax(300px,1fr))] mt-5 pb-6">
            {/* Mapping through videos to render a VideoItem for each */}
            {videos.map((video) => (
              <VideoItem key={video.id} video={video} />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;
```
Once you’ve completed all the steps, congratulations! You should now be able to see the YouTube homepage clone in your browser.

![Create A YouTube Homepage Clone in Tailwind CSS and ReactJS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dypfyyri1dnszoxkpg5l.jpg)

## Conclusion and final words
In conclusion, creating a YouTube homepage clone using React.js and Tailwind CSS is a great way to enhance your web development skills. By following the steps outlined in this [blog](https://www.codingnepalweb.com/category/blog/), you have successfully created a clone of the YouTube homepage on your own.

If you encounter any issues while working on your YouTube homepage clone project, you can download the source code files for free by clicking the “Download” button. You can also view a live demo by clicking the “View Live” button.”

After downloading the zip file, unzip it and open the “youtube-homepage-clone” folder in VS Code. Then, open the terminal by pressing Ctrl + J and run these commands to view your project in the browser:

```
npm install
npm run dev
```
[View Live Demo](https://www.codingnepalweb.com/demos/create-youtube-homepage-tailwind-reactjs/)

[Download Code Files](https://www.codingnepalweb.com/create-youtube-homepage-tailwind-reactjs/)