StreamHuddle is the ultimate multi-stream viewing platform—beautifully designed, highly customizable, and built for modern viewers. Watch up to 20 live streams simultaneously across Twitch, YouTube, and Kick with a unified, draggable, and dynamic layout.
- Multi-Streaming Setup: Seamlessly pull in streams from multiple major platforms like Twitch, YouTube, and Kick in a single window.
- Draggable & Resizable Grid: Fully customizable viewing layout. Resize and drag streams into any configuration you want using a beautiful, responsive interface.
- Saved Layouts: Save your favorite multi-stream setups (e.g. "Night Stream") and instantly load them back.
- Universal Chat: Consolidate chats from all your active streams into one unified sidebar.
- Dynamic Resizing: Chat windows smartly adjust as you customize your grid.
- Chat Command Integration: Viewers can submit clips directly via Twitch chat by typing
!queue <url>. The invisibleChatQueueListenerautomatically catches these and adds them to the live queue. - Real-Time Leaderboard Widget: A dynamic, live-updating
ClipQueueWidgeton the streamer's profile showing approved clips sorted by upvotes. - Upvoting: Viewers can upvote their favorite clips. Clips from the same URL are automatically deduplicated to pool upvotes together.
- Global Leaderboard: The multi-stream squad view aggregates clips across multiple streamers.
- Streamer Control Panel: A dedicated interface for streamers to manage their clip queue in real-time. Approve, reject, mark as played, or permanently delete clips.
- Twitch Integration: Secure OAuth authentication and token management for fetching high-quality streams and clips.
- Sleek, Dark UI: A modern, premium, dark-themed dashboard focused on performance and aesthetics.
| Category | Technologies |
|---|---|
| Frontend | TanStack Start, React 19, TypeScript |
| Backend / Realtime | Convex |
| Authentication | Better Auth (Email/Password, OTP, Google, Twitch) |
| Styling | Tailwind CSS v4, shadcn/ui, Motion (Framer Motion) |
| Deployment | Cloudflare Pages |
| Build | Vite with custom Node.js build runner |
StreamHuddle utilizes a highly optimized, modern architecture:
- TanStack Start: Powers the frontend routing and Server-Side Rendering (SSR).
- Convex: Provides the backend database and real-time synchronization. Components subscribe to live queries, meaning UI updates (like clip upvotes) propagate instantly to all clients.
- Cloudflare Pages: Hosts the frontend application and serverless edge functions.
The backend uses Convex with the following primary tables:
| Table | Description |
|---|---|
users |
App-specific user data (bio, avatar, role, isPro). Extends Better Auth's identity management. |
events |
General containers for tournaments and shows. |
creators |
Streamer profiles (Twitch, YouTube, Kick) including live status, viewers, and avatars. |
roster |
Junction table mapping creators to specific events. |
layouts |
User-saved multi-stream setups (e.g. "Night Stream") and snapshot views. |
twitchTokens |
Cached App Access Tokens for Twitch API calls. |
clips |
Records of clips being processed, generated, and downloaded via Convex R2 workflow. |
twitchUserTokens |
User OAuth tokens required for Twitch integrations. |
clipQueue |
Viewer-submitted clips awaiting streamer review or playback. |
clipQueueVotes |
Tracks individual user upvotes on clip queue items. |
The Clip Queue is a real-time, interactive feature that brings streamers and viewers closer together:
- Submission: A viewer drops a clip link in the streamer's Twitch chat using
!queue <url>. - Listening: The
ChatQueueListener.tsx(usingtmi.js) intercepts the message client-side and triggers a Convex mutation to add the clip to the queue. - Voting: Viewers see the clip appear instantly in the
ClipQueueWidgeton the streamer's page. They can click to upvote. Data syncs in real-time across all active viewers. - Moderation: The streamer uses the
StreamerControlPanelto review the top clips. They can mark clips as "Played" (removing them from the active list) or delete inappropriate clips.
git clone https://github.com/StreamHuddleHQ/streamhuddle.git
cd streamhuddle
bun install
bun run setup
bun run devOpen http://localhost:3000 to view the app locally.
The application requires environment variables defined during the build step and in the Cloudflare deployment.
Required variables in wrangler.toml (Build Time):
VITE_CONVEX_URL: The URL to your Convex deployment.VITE_CONVEX_SITE_URL: The URL to your Convex HTTP site routing.SITE_URL/VITE_SITE_URL: The production URL of the app.
Required variables in Convex (.env.convex.example / Convex Dashboard):
BETTER_AUTH_SECRET: Secret used for signing auth tokens.TWITCH_CLIENT_ID&TWITCH_CLIENT_SECRET: For Twitch API integration.RESEND_*: For email services.
StreamHuddle is configured to deploy seamlessly to Cloudflare Pages.
Deploying a TanStack Start app on Cloudflare Pages requires rendering with Vite. When Vite spins up the prerenderer, it uses the cloudflare-pages Nitro preset, spawning a wrangler pages dev child process (workerd).
Normally, this keeps Node's event loop alive, causing Cloudflare Pages CI builds to hang indefinitely until a 20-minute timeout occurs.
To fix this, we use a custom scripts/build.mjs runner that calls Vite's JS API (build()). Once the promise resolves, we explicitly call process.exit(0) to instantly reap dangling handles and exit cleanly.
bun run build
# Or deploy using wrangler:
bun run deployconvex/— Backend logic, real-time database schemas (schema.ts), serverless functions (clipQueue.ts,clips.ts), and workflows.src/components/— React UI components.clip-queue/— Dedicated components for the clip queue feature (ChatQueueListener.tsx,ClipQueueWidget.tsx,StreamerControlPanel.tsx).
src/routes/— TanStack Start file-based routing. Includes core pages likestreamer.$username.tsx.scripts/— Build and setup scripts.
If you enjoy using StreamHuddle, consider supporting the development!
This project is licensed under the GNU Affero General Public License v3.0 (AGPLv3).
