Shorts Jam: The Story Behind Synchronized Social Watching
Inspiration
The idea for Shorts Jam was born from a simple observation: we're more connected than ever, yet we scroll alone.
During the pandemic, we watched friends and family consume endless hours of YouTube Shorts in isolation. While the algorithm is great at personalizing content, it creates echo chambers and eliminates the shared experience of discovering content together. We asked ourselves: What if watching short-form content could be as social as watching a movie together?
Traditional watch parties focus on long-form content, but short-form videos present unique challenges: rapid content switching, diverse preferences, and the need for real-time synchronization. We wanted to solve this.
What We Learned
Technical Discoveries
Real-time Synchronization is Hard: Keeping multiple users perfectly in sync required deep understanding of WebSocket architecture and state management. We learned to handle race conditions, network latency (approx 50-200ms), and graceful degradation.
YouTube IFrame API Mastery: The auto-advance feature required mastering YouTube's Player API, understanding state change events, and handling edge cases like failed loads and network interruptions.
Database Design for Real-time: Structuring Supabase tables with proper RLS policies while maintaining real-time subscriptions taught us the balance between security and performance.
Soft Skills
- Minimalist Design Philosophy: Less is more. We learned to ruthlessly cut features that didn't serve the core experience.
- User-Centric Thinking: Every decision was tested against "Does this make watching together easier?"
How We Built It
Architecture Overview
┌─────────────┐
│ React UI │
│ (TypeScript)│
└──────┬──────┘
│
├──── Supabase Realtime ────┐
│ (WebSocket) │
│ ▼
│ ┌───────────────┐
│ │ Database │
│ │ - sessions │
│ │ - participants│
│ │ - queue │
│ │ - votes │
│ │ - chat │
│ └───────────────┘
│
└──── YouTube IFrame API
(Video Playback)
Tech Stack
- Frontend: React 18 + TypeScript + Vite
- Styling: Tailwind CSS + shadcn/ui components
- Backend: Supabase (PostgreSQL + Real-time + Edge Functions)
- Video: YouTube IFrame Player API
- State Management: React hooks + Supabase subscriptions
Key Features Implementation
1. Smart Algorithm Rotation
// Probability of playing from feed vs queue
P(queue) = queue.length > 0 ? 1.0 : 0.0
P(feed) = 1.0 - P(queue)
// Round-robin feed selection
next_user_index = (current_index + 1) mod total_participants
2. Real-time Presence Tracking
Used Supabase Presence API to track who's actively watching:
- Updates every 30 seconds
- Graceful handling of disconnections
- Visual indicators for active participants
3. Synchronized Playback
// State synchronization formula
video_time = start_timestamp + (current_time - playback_started_at)
sync_offset = |client_time - video_time|
if (sync_offset > 2000ms) {
resync_player()
}
Challenges We Faced
Challenge 1: Race Conditions in Vote Counting
Problem: Multiple users voting simultaneously caused incorrect skip counts.
Solution: Implemented optimistic UI updates with PostgreSQL's UPSERT pattern:
INSERT INTO votes (user_id, session_id, vote)
VALUES ($1, $2, $3)
ON CONFLICT (user_id, session_id)
DO UPDATE SET vote = $3, updated_at = NOW();
Challenge 2: Auto-Advance Without Infinite Loops
Problem: The onNextVideo callback in the YouTube player event listener would sometimes trigger multiple times, creating a cascade effect.
Solution: Added cleanup logic and proper dependency arrays in React's useEffect, ensuring the player destroys and recreates cleanly on video changes.
Challenge 3: Feed Depletion
Problem: What happens when a user's feed runs out?
Solution: Created a fallback placeholder feed generator and automatic feed rotation. When a feed ends, we move to the next participant's feed:
const handleFeedDepletion = (currentUserId) => {
const nextUser = participants.find(
p => p.id !== currentUserId && hasFeedItems(p)
);
return nextUser || generatePlaceholderFeed();
}
Challenge 4: Mobile Responsiveness
Problem: YouTube's 9:16 aspect ratio videos needed to work perfectly on all screen sizes.
Solution: CSS aspect-ratio property combined with responsive containers:
aspect-ratio: 9/16;
max-width: min(100%, 448px);
Challenge 5: No-Auth Instant Join
Problem: Traditional authentication flows create friction. We wanted instant access.
Solution: Implemented a participant-based system with 6-character join codes. Each participant gets a UUID stored in URL params—no email, no password, just instant connection.
Future Improvements
- Content filtering: Age ratings and category preferences
- Playlist mode: Pre-curated watch parties
- Reactions: Real-time emoji reactions synchronized with video playback
- Analytics: Track watch history and popular videos
- Mobile app: Native iOS/Android experience
What We're Proud Of
We built a fully functional, real-time social experience from scratch in record time. Shorts Jam proves that technology can enhance human connection rather than isolate us. Every feature was designed with one question: "Does this bring people closer together?"
The answer? Yes.
Try it yourself: Create a jam session and share the code with friends. Experience the joy of watching together.
Create About/Story Page Create Demo Video Section
Built With
- lovable
- typescript
Log in or sign up for Devpost to join the conversation.