Real-time video synchronization platform that lets you watch YouTube videos together with friends, no matter where they are.
- Real-time Synchronization - Watch videos in perfect sync with latency monitoring
- Unlimited Rooms - Create unlimited rooms with no user limits
- User Authentication - Secure login and registration system
- Participant Tracking - See who's watching with you in real-time
- YouTube Integration - Supports all YouTube videos via iframe API
- Responsive Design - Works on desktop and mobile devices
- Voice Chat - Built-in WebRTC voice communication
- Collaborative Control - Optional setting to allow all participants to control video
- Room Management - Public/private rooms with tags and descriptions
- NestJS - Progressive Node.js framework
- Socket.IO - Real-time bidirectional communication
- Prisma - Next-generation ORM for PostgreSQL
- PostgreSQL - Relational database
- JWT - Authentication tokens
- React - UI library
- TypeScript - Type safety
- Socket.IO Client - WebSocket connection
- Emotion - CSS-in-JS styling
- React Query - Data fetching and caching
Make sure you have these installed:
- Node.js (v18 or higher)
- PostgreSQL (v14 or higher)
- npm or yarn
cd Mustard-Watch-Party-
Start PostgreSQL service:
brew services start postgresql@14
-
Create database and user:
psql postgres -c "CREATE USER videouser WITH PASSWORD 'videopass';" psql postgres -c "CREATE DATABASE videosync OWNER videouser;" psql postgres -c "GRANT ALL PRIVILEGES ON DATABASE videosync TO videouser;"
-
Navigate to backend directory:
cd video-sync-backend -
Install dependencies:
npm install
-
Create environment file (.env):
echo 'DATABASE_URL="postgresql://videouser:videopass@localhost:5432/videosync"' > .env echo 'JWT_SECRET="your-super-secret-jwt-key-change-this-in-production"' >> .env echo 'PORT=3000' >> .env echo 'FRONTEND_URL="http://localhost:3001"' >> .env
-
Run database migrations:
npx prisma migrate deploy
-
Start the backend server:
npm run start:dev
Expected output: You should see:
β Database connected successfully π Server is running on http://localhost:3000 π WebSocket server is ready for connections
-
Open a new terminal and navigate to frontend directory:
cd video-sync-frontend -
Install dependencies:
npm install
-
Create environment file (.env):
echo 'REACT_APP_API_URL=http://localhost:3000/api' > .env echo 'REACT_APP_WS_URL=ws://localhost:3000' >> .env
-
Start the frontend server:
PORT=3001 npm start
Expected output: You should see:
Compiled successfully! You can now view video-sync-frontend in the browser. Local: http://localhost:3001
- Backend API: http://localhost:3000/api
- Frontend App: http://localhost:3001
-
Test backend API:
curl http://localhost:3000/api/rooms/public
Should return:
[] -
Test frontend: Open http://localhost:3001 in your browser
If backend fails to start:
- Check if PostgreSQL is running:
brew services list | grep postgres - Verify database connection:
psql -U videouser -d videosync -h localhost
If frontend fails to start:
- Make sure port 3001 is available
- Check if backend is running on port 3000
If you get database errors:
- Drop and recreate the database:
psql postgres -c "DROP DATABASE IF EXISTS videosync;" psql postgres -c "CREATE DATABASE videosync OWNER videouser;" npx prisma migrate deploy
You can create a quick start script. Create a file called start.sh in the root directory:
#!/bin/bash
# Start PostgreSQL
brew services start postgresql@14
# Start Backend
cd video-sync-backend
npm run start:dev &
# Start Frontend
cd ../video-sync-frontend
PORT=3001 npm startMake it executable: chmod +x start.sh
- Backend API: http://localhost:3000
- Frontend App: http://localhost:3001
- WebSocket: ws://localhost:3000
- Database: localhost:5432
Terminal 1 - Start Backend:
cd Mustard-Watch-Party/video-sync-backend
npm run start:devTerminal 2 - Start Frontend:
cd Mustard-Watch-Party/video-sync-frontend
PORT=3001 npm start- Register/Login - Create an account or login
- Create Room - Enter room name and YouTube URL
- Share Room Code - Give the code to friends
- Watch Together - Videos stay in sync automatically!
βββββββββββββββ WebSocket βββββββββββββββ
β React β ββββββββββββββββββ β NestJS β
β Frontend β β Backend β
βββββββββββββββ ββββββββ¬βββββββ
β
βββββββΌββββββ
βPostgreSQL β
β DB β
βββββββββββββ
- WebSocket Gateway - Handles real-time video state synchronization
- Room Service - Manages room creation and participant tracking
- Auth Service - JWT-based authentication
- Video Player - YouTube iframe API integration with sync logic
# Run with Docker Compose
docker-compose up --build
# Access at:
# Frontend: http://localhost:3001
# Backend: http://localhost:3000DATABASE_URL=postgresql://videouser:videopass@localhost:5432/videosync
PORT=3000
FRONTEND_URL=http://localhost:3001
JWT_SECRET=your-secret-keyREACT_APP_API_URL=http://localhost:3000/api
REACT_APP_WS_URL=ws://localhost:3000
PORT=3001| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register |
Register new user |
| POST | /api/auth/login |
Login user |
| POST | /api/rooms |
Create room (supports allowGuestControl flag) |
| GET | /api/rooms/public |
List public rooms |
| GET | /api/rooms/:code |
Get room details |
| GET | /api/rooms/user/:userId |
User's rooms |
| PATCH | /api/rooms/:code |
Update room |
| DELETE | /api/rooms/:code |
Delete room (host only) |
This project is licensed under the Apache 2.0 License.
- Built with β€οΈ for movie nights with friends
- Inspired by the need to stay connected while apart
Happy Watching! π¬