Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📺 YouTube Clone

A cloud-native video-sharing platform built with Next.js, Firebase, Google Cloud Storage, Cloud Pub/Sub, and Cloud Run. Users can sign in with Google, upload videos, and watch them after automatic server-side transcoding to 360p.

Next.js TypeScript Firebase Docker Google Cloud


How It Works

The app is split into three independent services that communicate through Google Cloud infrastructure:

┌─────────────────┐       ┌───────────────────────┐       ┌────────────────────────┐
│  Next.js Client │──────▶│  Firebase Cloud Funcs  │──────▶│       Firestore         │
│  (yt-web-client)│       │  (yt-api-service)      │       │  (users & videos meta)  │
└────────┬────────┘       └───────────────────────┘       └────────────────────────┘
         │                                                           ▲
         │  PUT (signed URL)                                         │ status update
         ▼                                                           │
┌─────────────────┐   Object Finalize   ┌──────────┐   HTTP POST   ┌┴───────────────────────┐
│  GCS Raw Bucket │───────────────────▶│ Pub/Sub  │──────────────▶│  Video Processing Svc  │
└─────────────────┘                    └──────────┘               │  (Cloud Run + ffmpeg)  │
                                                                   └───────────┬────────────┘
                                                                               │ upload
                                                                               ▼
                                                                   ┌─────────────────────┐
                                                                   │ GCS Processed Bucket │
                                                                   │   (public access)    │
                                                                   └─────────────────────┘
  1. Sign in — User authenticates via Google OAuth through Firebase Auth. A Cloud Function trigger automatically creates a user document in Firestore.
  2. Upload — The client requests a time-limited signed URL from a Cloud Function, then uploads the video file directly to a GCS raw bucket (the video never passes through the API).
  3. Process — GCS emits an object-finalize event → Pub/Sub → pushes an HTTP message to the video processing service on Cloud Run → ffmpeg transcodes the video to 360p → the result is uploaded to a processed bucket and made public.
  4. Watch — The client reads video metadata from Firestore and streams the processed video directly from the public GCS bucket using an HTML5 <video> element.

Project Structure

youtube-clone/
├── yt-web-client/               # Next.js 14 frontend
│   ├── app/
│   │   ├── firebase/            # Firebase SDK init, auth helpers, callable functions
│   │   ├── navbar/              # Navbar, Sign-In, and Upload components
│   │   ├── watch/               # Video watch page
│   │   ├── layout.tsx           # Root layout with Navbar
│   │   └── page.tsx             # Home page — lists uploaded videos
│   └── Dockerfile               # Multi-stage build for Cloud Run
│
├── yt-api-service/              # Firebase Cloud Functions (API layer)
│   └── functions/src/index.ts   # createUser, generateUploadUrl, getVideos
│
├── video-processing-service/    # Express + ffmpeg (runs on Cloud Run)
│   └── src/
│       ├── index.ts             # POST /process-video endpoint
│       ├── storage.ts           # GCS upload/download, ffmpeg transcoding
│       └── firestore.ts         # Video metadata read/write
│
└── utils/
    └── gcs-cors.json            # CORS config for the raw video bucket

Prerequisites


Setup

1. Google Cloud & Firebase

# Login to Google Cloud and Firebase
gcloud auth login
firebase login

# Create a new Firebase project (or use an existing one)
firebase projects:create <your-project-id>

# Enable required APIs
gcloud services enable \
  run.googleapis.com \
  pubsub.googleapis.com \
  storage.googleapis.com \
  firestore.googleapis.com \
  cloudbuild.googleapis.com \
  --project=<your-project-id>

2. Cloud Storage Buckets

Create two buckets — one for raw uploads and one for processed videos:

gsutil mb -l us-central1 gs://<your-raw-video-bucket>
gsutil mb -l us-central1 gs://<your-processed-video-bucket>

Apply the CORS configuration so the browser can upload directly:

gsutil cors set utils/gcs-cors.json gs://<your-raw-video-bucket>

3. Cloud Pub/Sub

Create a topic and a push subscription that points to your Cloud Run video processing service:

# Create the topic
gcloud pubsub topics create <your-topic-name>

# Set up a GCS notification on the raw bucket
gsutil notification create -t <your-topic-name> -f json gs://<your-raw-video-bucket>

# After deploying the processing service (step 5), create the push subscription:
gcloud pubsub subscriptions create <your-sub-name> \
  --topic=<your-topic-name> \
  --push-endpoint=<your-cloud-run-url>/process-video \
  --ack-deadline=600

4. Firebase Cloud Functions (API Service)

cd yt-api-service

# Install dependencies
cd functions && npm install && cd ..

# Update bucket names in functions/src/index.ts:
#   const rawVideoBucketName = "<your-raw-video-bucket>";

# Deploy
firebase deploy --only functions

5. Video Processing Service (Cloud Run)

cd video-processing-service

# Update bucket names in src/storage.ts:
#   const rawVideoBucketName = "<your-raw-video-bucket>";
#   const processedVideoBucketName = "<your-processed-video-bucket>";

# Build and push the Docker image
gcloud builds submit --tag gcr.io/<your-project-id>/video-processing-service

# Deploy to Cloud Run
gcloud run deploy video-processing-service \
  --image gcr.io/<your-project-id>/video-processing-service \
  --platform managed \
  --region us-central1 \
  --memory 2Gi \
  --timeout 900 \
  --allow-unauthenticated

6. Web Client (Next.js)

cd yt-web-client

# Install dependencies
npm install

# Create a .env file with your Firebase config
cat > .env << EOF
NEXT_PUBLIC_FIREBASE_KEY=<your-api-key>
NEXT_PUBLIC_AUTH_DOMAIN=<your-project>.firebaseapp.com
NEXT_PUBLIC_PROJECT_ID=<your-project-id>
NEXT_PUBLIC_STORAGE_BUCKET=<your-project>.appspot.com
NEXT_PUBLIC_MESSAGING_SENDER_ID=<your-sender-id>
NEXT_PUBLIC_FIREBASE_APP_ID=<your-app-id>
NEXT_PUBLIC_MEASUREMENT_ID=<your-measurement-id>
EOF

# Update the processed video bucket URL in app/watch/page.tsx:
#   const videoPrefix = 'https://storage.googleapis.com/<your-processed-video-bucket>/';

# Run locally
npm run dev

Open http://localhost:3000 to see the app.

To deploy the client to Cloud Run:

gcloud builds submit --tag gcr.io/<your-project-id>/yt-web-client
gcloud run deploy yt-web-client \
  --image gcr.io/<your-project-id>/yt-web-client \
  --platform managed \
  --region us-central1

Tech Stack

Layer Technology Purpose
Frontend Next.js 14, React 18, TypeScript Server & client-side rendering, routing
Auth Firebase Authentication Google OAuth sign-in
API Firebase Cloud Functions Signed URL generation, video metadata queries
Message Queue Google Cloud Pub/Sub Decouples upload events from processing
Video Processing Express, fluent-ffmpeg, Cloud Run Transcodes videos to 360p inside Docker
Database Cloud Firestore Stores user profiles and video metadata
Storage Google Cloud Storage Raw & processed video file storage
Containerization Docker (multi-stage builds) Lean production images for Cloud Run

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages