Watch Together. Chat Together. Be Together.
A real-time, Java Full-Stack watch party application for synchronized video viewing, interactive polls, Q&A, whiteboard, and WebRTC video/voice calls with friends.
- YouTube Integration β Paste any YouTube URL or search YouTube directly within the room; videos sync across all participants in real time.
- Local File Support β Upload and play local video files directly in the browser.
- Play / Pause / Seek Sync β Every action is broadcast via Socket.IO/WebSockets with sub-second synchronization.
- Video Queue β Add multiple videos to a collaborative queue, reorder, or autoplay the next item.
- Instant Messaging β Low-latency chat broadcast to all room participants.
- AI Assistant Integration β Mention
@ai <query>to get instant answers in chat powered by OpenRouter / Gemini. - User Avatars β Profile pictures and DiceBear adventurer avatars displayed alongside messages.
- Emoji Reactions β Interactive emoji bursts appearing dynamically on screen for all members.
- Peer-to-Peer Video β Direct WebRTC connections via PeerJS signaling.
- Camera & Mic Controls β Easy toggling of audio/video streams with state sync.
- Screen Sharing β Real-time screen capture sharing with automatic reversion to camera.
- Tab-Switch Media Recovery β Seamless media track recovery when returning from inactive tabs.
- Collaborative Whiteboard β Real-time drawing canvas synced among participants.
- Live Polls β Create polls, vote in real-time, close, and view instant results.
- Interactive Q&A β Post questions, upvote popular questions, and submit answers.
- Host Moderation β Primary owner controls: kick users, force mute, lower all hands, transfer host permissions.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (Next.js 14 / React 18) β
β Landing Page βββΊ Dashboard βββΊ Watch Room β
β (Google OAuth) (Create/Join) (Video + Chat + WebRTC + Tools)β
β β
β State: Zustand β Hooks: useWebRTC β UI: shadcn/ui + Tailwind β
ββββββββββββββ¬βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β REST API + Socket.IO β WebRTC PeerJS Signaling
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Backend (Java 25 + Spring Boot 4) β
β Port: 4000 β
β β
β β’ Spring MVC REST Controllers (/api/users, /api/rooms, /health)β
β β’ Spring Data JPA Repositories (PostgreSQL / Supabase) β
β β’ Spring Security 6 + JWT Stateless Authentication β
β β’ Spring WebSocket (Socket.IO v4 Engine + PeerJS Signaling) β
β β’ In-Memory Thread-Safe RoomStateManager β
β β’ AI Assistant Service (OpenRouter / Gemini) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Supabase / PostgreSQL Database β
β Tables: users β user_recent_rooms β rooms β messages β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Java: JDK 25+ (
java -version) - Maven: 3.9+ (
mvn -version) - Node.js: v18+ (
node -v) - Python: 3.10+ (for metadata service)
- Supabase / PostgreSQL: Hosted Supabase project or local PostgreSQL instance (port 5432).
-
Navigate to the
backenddirectory:cd backend -
Configure environment properties in
src/main/resources/application.properties(or set environment variables):server.port=4000 spring.datasource.url=jdbc:postgresql://localhost:5432/syncroom spring.datasource.username=postgres spring.datasource.password=postgres cors.allowed-origins=http://localhost:3000 jwt.secret=syncroom_jwt_super_secure_secret_key_minimum_256_bits_length_1234567890 youtube.api.key=YOUR_YOUTUBE_API_KEY # (Optional) openrouter.api.key=YOUR_OPENROUTER_API_KEY # (Optional)
Note for Supabase Cloud: For hosted Supabase, set
spring.datasource.url=jdbc:postgresql://db.<PROJECT_REF>.supabase.co:5432/postgres?sslmode=requireand use your Supabase database password. Runsupabase/schema.sqlin the Supabase SQL Editor. -
Build and run the backend:
# Run tests mvn clean test # Start Spring Boot application mvn spring-boot:run
The backend will start on
http://localhost:4000.
-
Navigate to the
frontenddirectory:cd frontend -
Install dependencies:
npm install
-
Ensure
.env.localis configured:NEXT_PUBLIC_SOCKET_URL=http://localhost:4000 NEXT_PUBLIC_PEER_HOST=localhost NEXT_PUBLIC_PEER_PORT=4000 NEXT_PUBLIC_PYTHON_SERVICE_URL=http://localhost:8000 NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=your_nextauth_secret
-
Start development server:
npm run dev
The frontend will run on
http://localhost:3000.
-
Navigate to
python-service:cd python-service -
Set up virtual environment and run:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -r requirements.txt uvicorn main:app --host 0.0.0.0 --port 8000 --reload
- Windows: Run
start-dev.bat - Linux / macOS: Run
./start-dev.sh
To spin up all services (PostgreSQL, Spring Boot Backend, Python Service, Next.js Frontend) simultaneously:
docker-compose up --build| Method | Endpoint | Description | Request Body / Params | Status |
|---|---|---|---|---|
GET |
/health |
Server health check | None | 200 OK |
POST |
/api/users/sync |
Sync user on sign-in | { "name": "...", "email": "...", "image": "..." } |
200 OK |
GET |
/api/users/profile |
Get user profile | ?email=user@example.com |
200 OK |
POST |
/api/users/profile/update |
Update name / avatar | { "email": "...", "name": "...", "image": "..." } |
200 OK |
GET |
/api/users/recent-rooms |
Fetch recent room history | ?email=user@example.com |
200 OK |
POST |
/api/users/recent-rooms |
Add room to history | { "email": "...", "roomId": "..." } |
200 OK |
GET |
/api/rooms/{roomId} |
Get room details | Path variable {roomId} |
200 OK |
POST |
/api/rooms/create |
Create new watch room | { "roomId": "...", "ownerId": "...", "isPrivate": false, "password": "..." } |
201 Created |
GET |
/api/youtube/search |
Search YouTube videos | ?q=search_query |
200 OK |
GET |
/peerjs/myapp/id |
PeerJS ID allocation | None | 200 OK |
| Layer / Feature | Original MERN Implementation | New Java Spring Boot Implementation |
|---|---|---|
| Server Framework | Express 5.x (server.js) |
Spring Boot 3.3.x (SyncRoomApplication.java) |
| ORM / Database | Mongoose (models/*.js) |
Spring Data JPA + Supabase / PostgreSQL (@Entity, JpaRepository) |
| Security & Auth | Custom Express handlers + JWT | Spring Security 6 (SecurityFilterChain, JwtTokenProvider, JwtAuthenticationFilter) |
| Password Hashing | Manual / Plaintext | BCrypt (BCryptPasswordEncoder) |
| Real-time Protocol | socket.io npm package |
Spring WebSocket (SocketIoWebSocketHandler Engine.IO 4 / Socket.IO 4 protocol) |
| WebRTC Signaling | peer npm package (ExpressPeerServer) |
Spring WebSocket (PeerJsWebSocketHandler + PeerJsHttpController) |
| In-Memory State | Node Map in socket/index.js |
Thread-safe RoomStateManager (ConcurrentHashMap) |
| AI Assistant | Node fetch to OpenRouter |
Spring RestClient in AiAssistantService |
| Build & Dependency | npm (package.json) |
Apache Maven (pom.xml) with Java 25 |
| Containerization | Node Dockerfile | Multi-stage Eclipse Temurin 25 Dockerfile |
| CI/CD | None | GitHub Actions (.github/workflows/ci.yml) |