Build a YouTube Live Clone with Next.js, Clerk, and TailwindCSS - Part One

Published: (December 12, 2025 at 12:56 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Ever wondered how livestream platforms broadcast real-time video to thousands of viewers?
In this two‑part series, you’ll learn how to build a YouTube Live clone using Next.js, TailwindCSS, and Stream. We’ll build the UI with TailwindCSS, set up authentication with Clerk, and use Prisma to model and persist the app data. Then we’ll integrate the Stream Video and Audio SDK for livestreaming, and include a live chat for each stream using the Stream Chat SDK. By the end, you’ll have a functional app that mirrors YouTube Live’s core features.

In this first part, we’ll set up the project, add authentication, and build the home page. You can view the live demo and access the complete source code on GitHub.

Prerequisites

  • Basic understanding of React.
  • Node.js and npm installed.
  • Familiarity with TypeScript, Next.js, and TailwindCSS.

Setting up the Next.js Project

# Clone the repository
git clone https://github.com/TropicolX/youtube-live-clone.git

# Navigate into the project directory
cd youtube-live-clone

# Check out the starter branch
git checkout starter

# Install the dependencies
npm install

Setting Up the Database

We’ll use Prisma with SQLite for development.

npm install prisma@6.19.0 --save-dev
npm install @prisma/client@6.19.0 sqlite3

Initialize Prisma:

npx prisma init

Edit prisma/schema.prisma:

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model Subscription {
  subscriberId String
  channelId    String
  createdAt    DateTime @default(now())
  @@id([subscriberId, channelId])
}

enum ReactionType {
  LIKE
  DISLIKE
}

model Reaction {
  userId        String
  livestreamId  String
  type          ReactionType
  createdAt     DateTime @default(now())
  @@id([userId, livestreamId])            // one reaction per user per livestream
  @@index([livestreamId, type])           // fast counts per type
}

Configuring the Database Connection

Add to .env:

DATABASE_URL=file:./dev.db

Run migrations and generate the client:

npx prisma migrate dev --name init
npx prisma generate

Create lib/prisma.ts:

import { PrismaClient } from '@prisma/client';

let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  // @ts-expect-error global.prisma is used in development
  if (!global.prisma) {
    // @ts-expect-error global.prisma is used in development
    global.prisma = new PrismaClient();
  }
  // @ts-expect-error global.prisma is used in development
  prisma = global.prisma;
}

export default prisma;

User Authentication with Clerk

What is Clerk?

Clerk provides user management, authentication, and profile handling out of the box.

Setting Up a Clerk Account

  1. Sign up at the Clerk website.
  2. In the dashboard, click Create application.
  3. Name it “Youtube Live Clone”.
  4. Enable “Email”, “Username”, and “Google” sign‑in options.
  5. Save the application and note the Publishable Key and Secret Key.

Configuring Required User Fields

  1. Go to the Configure tab → User model.
  2. Enable “Require first and last name”.
  3. Save changes.

Installing Clerk in Your Project

npm install @clerk/nextjs

Create .env.local:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up

Replace the placeholder values with the keys from your Clerk app.

Update app/layout.tsx (or app/layout.tsx if using the new App Router):

import type { Metadata } from 'next';
import { ClerkProvider } from '@clerk/nextjs';
import './globals.css';

export const metadata: Metadata = {
  title: 'YouTube Live clone',
  description: 'A YouTube Live clone built with Next.js and Stream.',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider>
      {children}
    </ClerkProvider>
  );
}

Creating the Sign‑Up and Sign‑In Pages

Create the sign‑up page at app/sign-up/[[...sign-up]]/page.tsx:

'use client';
import { SignUp } from '@clerk/nextjs';

export default function Page() {
  return (
    <SignUp />
  );
}

Create the sign‑in page at app/sign-in/[[...sign-in]]/page.tsx (similar structure, using SignIn):

'use client';
import { SignIn } from '@clerk/nextjs';

export default function Page() {
  return (
    <SignIn />
  );
}

Now Clerk handles authentication UI and logic throughout the app.

Back to Blog

Related posts

Read more »