Syncora System Design
Complete architecture, deployment guide, and setup instructions for the Syncora watch-together platform.
Table of Contents
System Architecture
Syncora is a full-stack monorepo with two applications shipping together: a NestJS backend and a Next.js 14 frontend. The system is designed for real-time watch-together experiences with sub-second video sync, encrypted chat, and HD video calls.
Tech Stack
Backend Modules
AuthModule
JWT auth (access + refresh tokens), email/password signup, Google OAuth, OTP email verification, password reset with expiring links
RoomsModule
CRUD for couple/friend rooms, invite codes (6-char), member management, kick/regenerate
ChatModule
Socket.IO gateway, encrypted messages (AES), image/GIF/sticker support, typing indicators, reactions, message deletion
UploadModule
Chunked multipart uploads (4MB chunks), server reassembly, 25MB room limit, 5MB per image, 6hr auto-cleanup
WatchModule
YouTube download via yt-dlp (max 3hr), video sync via Redis state, watch history/resume, adaptive quality
CallModule
LiveKit token generation, call state in Redis, couple/friend validation, incoming call notifications, call records in chat
AdminModule
Dashboard stats, user/room management, storage monitoring
MailModule
OTP, welcome, password reset emails with monochrome templates
Frontend Pages
/Marketing landing page (hero, features, how-it-works, pricing)/auth/*Login, signup, verify email, forgot/reset password, Google OAuth/dashboardRoom list, create/join rooms/room/[id]Chat room with WhatsApp-style messaging/room/[id]/callVideo call with 70/30 layout, airhorn sound/room/[id]/watchWatch together with sync player, YouTube download, library/adminAdmin dashboard with user/room statsData Flow
1. User signs up → OTP email → verify → login → JWT access (15min) + refresh (30d) cookies 2. Creates room → invite code generated → share with partner/friends 3. Chat: Socket.IO → encrypt message → store in Postgres → broadcast to room 4. Watch: Upload/YouTube link → server stores file → Redis sync state → all players sync 5. Call: Request LiveKit token → WebRTC peer connection → Redis call state → chat records
Security Features
Google OAuth Setup
Step 1: Create Google Cloud Project
- Go to console.cloud.google.com
- Click Select a project → New Project
- Name it
Syncora - Click Create
Step 2: Configure OAuth Consent Screen
- Go to APIs & Services → OAuth consent screen
- Select External user type → Create
- Fill in: App name =
Syncora, User support email = your email - Add Authorized domains:
bhupeshchauhan.in - Add Developer contact email → Save and Continue
- On Scopes page → Add scope:
openid,email,profile - Save and Continue → Back to Dashboard
Step 3: Create OAuth Credentials
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Application type: Web application
- Name:
Syncora Web - Authorized JavaScript origins:
https://syncora.bhupeshchauhan.inhttp://localhost:3000(for dev)
- Authorized redirect URIs:
http://localhost:3001/api/auth/google/callback
- Click Create
- Copy the Client ID and Client Secret
Step 4: Add to Environment Variables
# Backend .env
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
# Frontend .env.local
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
Domain & VPS Deployment
Step 1: Domain DNS Setup (Hostinger)
- Login to Hostinger → DNS / Nameservers
- Add DNS records:
Type: A | Name: @ | Value: YOUR_VPS_IP
Type: A | Name: admin | Value: YOUR_VPS_IP
Type: A | Name: www | Value: YOUR_VPS_IP
- Wait 5-30 minutes for DNS propagation
- Verify:
dig syncora.bhupeshchauhan.in
Step 2: VPS Setup (Ubuntu 22.04)
# SSH into your VPS
ssh root@YOUR_VPS_IP
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Clone the repo
git clone https://github.com/yourusername/Syncora.git
cd Syncora
# Install Certbot for SSL
sudo apt install certbot -y
sudo certbot certonly --standalone -d syncora.bhupeshchauhan.in -d admin.syncora.bhupeshchauhan.in
# Copy SSL certs
sudo cp /etc/letsencrypt/live/syncora.bhupeshchauhan.in/fullchain.pem nginx/certs/
sudo cp /etc/letsencrypt/live/syncora.bhupeshchauhan.in/privkey.pem nginx/certs/
Step 3: Configure & Deploy
- Edit
.envwith your credentials - Run:
bash deploy.sh - Verify:
docker compose -f docker-compose.prod.yml ps
Step 4: SSL Auto-Renewal
# Add cron job for auto-renewal
sudo crontab -e
Add this line:
0 3 * * 1 certbot renew --post-hook "cp /etc/letsencrypt/live/syncora.bhupeshchauhan.in/*.pem /home/user/Syncora/nginx/certs/ && docker compose -f /home/user/Syncora/docker-compose.prod.yml restart nginx"
Environment Variables
| Variable | Description | Example |
|---|---|---|
| DATABASE_URL | PostgreSQL connection string | postgresql://user:pass@host:5432/db |
| REDIS_URL | Redis connection string | redis://redis:6379 |
| JWT_SECRET | Secret for JWT signing | random-64-char-string |
| WEB_URL | Frontend URL | https://syncora.bhupeshchauhan.in |
| GMAIL_USER | SMTP email | your@gmail.com |
| GMAIL_APP_PASSWORD | Gmail app password | xxxx-xxxx-xxxx-xxxx |
| GOOGLE_CLIENT_ID | Google OAuth client ID | xxx.apps.googleusercontent.com |
| GOOGLE_CLIENT_SECRET | Google OAuth secret | GOCSPX-xxx |
| LIVEKIT_API_KEY | LiveKit API key | devkey |
| LIVEKIT_API_SECRET | LiveKit API secret | devkeysecret |
| LIVEKIT_URL | LiveKit WebSocket URL | wss://syncora.bhupeshchauhan.in/livekit |
| UPLOAD_DIR | File upload directory | /app/uploads |
| CHAT_ENCRYPTION_KEY | AES key for chat | same-as-jwt-secret |
| NEXT_PUBLIC_API_URL | Frontend API URL | https://syncora.bhupeshchauhan.in/api |
| NEXT_PUBLIC_GOOGLE_CLIENT_ID | Frontend Google client ID | xxx.apps.googleusercontent.com |
Built with care by Bhupesh Chauhan
Syncora — Watch Together. Feel Together.