Imported from BhushanLagare7/youtube-clone (
AGENTS.md). Install upstream withnpx skills add BhushanLagare7/youtube-clone. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
AGENTS.md
Welcome, AI coding agent! This file provides standard guidelines, environment configuration steps, development workflows, and coding conventions to help you work efficiently in this codebase.
Project Overview
This repository is a full-featured, production-grade YouTube Clone built using:
- Core Framework: Next.js 16 (App Router) & React 19
- Package Manager: Bun
- Database & ORM: Neon Serverless PostgreSQL + Drizzle ORM
- Authentication: Clerk (with webhook-based database synchronization)
- Styling: Tailwind CSS v4 + Radix UI + shadcn/ui + Tailwind Animate CSS
- API & Data Fetching: tRPC + TanStack React Query (
@trpc/client,@trpc/server,@trpc/tanstack-react-query) - Media Pipeline: Mux (video ingestion, streaming, player, auto-captions) & UploadThing (image/thumbnail uploads)
- Workflows & Cache: Upstash Redis, QStash, and Upstash Workflows
- AI Infrastructure: Google Gemini 2.5 Flash (via Vercel AI SDK) & Hugging Face (
FLUX.1-schnell) for automated metadata/thumbnail generation from video transcripts
Setup & Installation
Follow these steps to configure your environment:
-
Install Dependencies:
bun install -
Environment Variables: Copy
.env.exampleto.env.localand populate the required API keys and secrets:cp .env.example .env.localMake sure keys for Neon, Clerk, Mux, UploadThing, Upstash, Google Gemini, and Hugging Face are correctly configured.
-
Database Schema Setup: Initialize your Neon database and sync schemas using Drizzle Kit:
bunx drizzle-kit push -
Seed Categories: Populate initial database categories needed for video uploads:
bun src/scripts/seed-categories.ts
Development Workflow
Starting the Server
To support webhooks locally, the dev server runs concurrently with an ngrok tunnel on port 3000:
bun run dev:all
This runs:
next dev(development web server)ngrok http 3000(starts the local webhook forwarding tunnel)
Webhook & Workflow Setup
To receive callbacks from Clerk and Mux locally, update the service dashboards with your ngrok URL:
- Clerk Webhooks: Point to
https://<YOUR_NGROK_SUBDOMAIN>.ngrok-free.dev/api/users/webhookforuser.createdanduser.updatedevents. DefineCLERK_SIGNING_SECRETin.env.local. - Mux Webhooks: Point to
https://<YOUR_NGROK_SUBDOMAIN>.ngrok-free.dev/api/videos/webhook. DefineMUX_WEBHOOK_SECRETin.env.local. - Upstash Workflows: Set
UPSTASH_WORKFLOW_URLto your ngrok base URL, and setQSTASH_DEV=truefor local workflow processing.
Database & Schema Management
All schemas are located in src/db/schema.ts.
- Pushing Schema Updates: Run
bunx drizzle-kit pushto push schema changes directly to Neon PostgreSQL. - Generating Migrations: If manual migration scripts are needed, run:
bunx drizzle-kit generate - Drizzle Studio: Run the database dashboard to view and manage tables:
bunx drizzle-kit studio
Project Structure
This project follows a domain-modular structure located inside src/modules. Avoid creating top-level folders inside src/ for feature-specific code.
src/
├── app/ # Next.js App Router (Layouts, pages, sitemaps, robots)
├── components/ # Globally shared UI components (SEO, Error boundaries, etc.)
├── db/ # Database client, schemas, and queries
├── hooks/ # Globally reusable React hooks
├── lib/ # Service clients (Clerk, Mux, Upstash, Google AI SDK, UploadThing, tRPC)
├── modules/ # Domain-specific modules:
│ ├── auth/ # Clerk auth components, sync procedures, and hooks
│ ├── categories/ # Video categories, hooks, and schemas
│ ├── comments/ # Nesting comment threads, reply structures, reactions
│ ├── playlists/ # Playlist management UI, components, and trpc hooks
│ ├── studio/ # Creator Studio layout, upload interface, video details edit
│ ├── subscriptions/ # Subscriptions UI, procedures, and logic
│ └── videos/ # Video components, reactions, playback UI, and AI transcript workflows
├── scripts/ # Migration/seeding helper scripts
└── trpc/ # tRPC router declarations and server query query runners
Code Style & Linting Guidelines
Follow these strict guidelines when modifying or creating files:
1. Import Sorting
We use eslint-plugin-simple-import-sort. Imports must be sorted automatically using bun run lint:fix or by organizing them in the following order:
- React and Next.js Core Libraries (e.g.,
react,next/navigation) - Third-Party Node Packages (e.g.,
@clerk/nextjs,@trpc/server,zod) - Internal Aliases starting with
@/(e.g.,@/db/schema,@/lib/utils) - Parent Directory Imports (e.g.,
../components) - Sibling Directory Imports (e.g.,
./VideoCard) - Side-effect Imports (e.g.,
import "./globals.css")
2. JSX Props Sorting
We enforce strict JSX prop sorting. Ensure all component props are sorted alphabetically, with custom event callbacks placed last and reserved props (like key or ref) placed first.
Run the linter to verify or fix code styling:
- Check rules:
bun run lint - Apply fixes:
bun run lint:fix
3. File and Variable Naming
- Use kebab-case for filenames unless defining React components (PascalCase or kebab-case).
- Keep component files simple, reusable, and single-purpose. Defer database logic/API queries to tRPC routes inside
src/trpc/and call them via tRPC query hooks.
4. Database Querying & tRPC Procedures
- Implementation vs. Composition: Domain-specific procedure logic should live under the relevant module's server directory (e.g.,
src/modules/videos/server/procedures.ts). Shared database/API utilities belong insrc/trpc/only where appropriate, and routers should be composed there. Do not put domain logic directly insrc/trpc/. - Shared DB Utilities: When writing tRPC procedures, always use the shared utilities from
@/lib/db-utils.tsfor common boilerplate:- Use
paginateResults()for cursor-based pagination (the "limit + 1" pattern). - Use
getInternalUserId()to cleanly map a Clerk ID to an internal DB user ID. - Use
getVideoEngagementCounts()to pull consistent video statistics (views, likes, dislikes) instead of redefining$countstatements.
- Use
- Domain Independence: Do not create fully generic entity fetchers (e.g.,
getAnyEntityOrThrow) as different domains (Videos, Playlists) may have distinct ownership validation rules (e.g., soft deletes, team ownership). Keep methods localized to their specific module (e.g.,getVideoOrThrowinsrc/modules/videos/server/procedures.ts).
Verification & Testing
- Testing: There is no testing framework (like Jest or Playwright) configured in this repository. Ensure code accuracy through manual verification, lint checks, and successful production builds.
- Linting Verification:
bun run lint - Build Verification: Before committing or opening a PR, always confirm the Next.js app builds cleanly:
bun run build