Let your audience decide what plays next — or pay to skip the queue.
Votetunes is a real-time collaborative music queue for live streamers. Your audience can vote on songs in the regular queue, or pay via Razorpay to jump straight to the top of a priority lane. As a creator, you control what plays.
| Role | How to Access | What They Can Do |
|---|---|---|
| Creator | Log in → Dashboard (/dashboard) |
Submit songs, advance the queue (priority & regular), share their stream link |
| Audience | Shared link → /creator/<id> |
Submit songs, vote up/down in the regular queue, make priority payment requests |
Share your stream: From the Dashboard, click the Share Stream button — it copies
/creator/<your-user-id>to send to your audience.
┌──────────────────────────────────────────────────┐
│ Browser │
│ │
│ ┌────────────┐ ┌──────────────┐ │
│ │ Creator │ │ Audience │ │
│ │ (Dashboard)│ │ (/creator/*) │ │
│ └─────┬──────┘ └──────┬───────┘ │
│ └─────────┬────────┘ │
│ │ Next.js App Router │
└──────────────────┼──────────────────────────────-┘
│
┌──────────▼───────────┐
│ API Routes (/api) │
│ │
│ GET /streams │ ← initial load & fallback polling
│ POST /streams │ ← add to queue & triggers Pusher event
│ POST /streams/upvote│ ← vote up & triggers Pusher event
│ POST /streams/downvote ← vote down & triggers Pusher event
│ GET /streams/playnext?isPriority=true|false
│ POST /create-order │ ← Razorpay order
│ POST /verify-payment│ ← marks COMPLETED
└──────────┬───────────┘
│ Prisma ORM
┌──────────▼───────────┐
│ MySQL │
│ │
│ User │
│ Stream │
│ Payment (optional) │
│ CurrentStream │
│ Upvote │
└──────────────────────┘
▲ verify
│
┌─────┴──────┐
│ Razorpay │
└────────────┘
INCOMING SONGS
│
├─── paid (Razorpay completed) ──► 💰 PRIORITY LANE
│ sorted by: amount DESC, time ASC
└─── free ────────────────────────► 🗳️ REGULAR LANE
sorted by: votes DESC
PLAY NEXT (creator action or auto on song end):
if priority lane is not empty → play top priority
else → play top of regular lane
- 🎛️ Creator Dashboard — your personal stream hub at
/dashboard ▶️ Manual queue control — skip to next video from either lane- ⭐ Priority-first auto-play — when a video ends, priority lane drains first automatically
- 📤 One-click share — share your audience link from the dashboard
- 🏷️ Creator badge — visual indicator showing you're the owner of the stream
- 🔗 Shareable stream URL —
/creator/<id>for audience to join - 🎵 Song submission — paste any YouTube URL to add to the queue
- 🗳️ Democratic voting — upvote/downvote with optimistic UI updates
- 💰 Priority requests — pay ₹100–₹1000 via Razorpay to jump to the top
- 👑 Priority queue visibility — see the full paid queue sorted by amount
- 🔐 Google OAuth via NextAuth.js
- 🔄 Real-Time Sync — instant queue updates using Pusher WebSockets (with automatic 5-second polling fallback if credentials are omitted)
- 🎬 Embedded YouTube player via
yt-playerwith autoplay - 💸 Payments — Razorpay checkout → server-side verification → DB update
All payments via Razorpay flow directly into the Razorpay merchant account linked to the API keys in your .env:
RAZORPAY_KEY_ID → the merchant's account
RAZORPAY_KEY_SECRET → used to sign & verify webhooks
If you self-host Votetunes you keep 100% of priority request revenue. A multi-tenant platform split (e.g. 80% creator / 20% platform) would require Razorpay Route.
| Feature | Status |
|---|---|
| YouTube priority queue | ✅ Live |
| Razorpay priority payments | ✅ Live |
| Optimistic voting | ✅ Live |
| Auto-play with priority-first logic | ✅ Live |
| WebSocket / SSE real-time push | ✅ Live (via Pusher) |
| OBS browser-source overlay | 🔧 Planned |
| Spotify integration | 🔧 Planned |
| Multi-tenant creator accounts | 🔧 Planned |
| Tipping without a song request | 🔧 Planned |
git clone https://github.com/yourname/votetunes.git
cd votetunes
npm installCreate a .env file in the project root:
DATABASE_URL="mysql://user:password@localhost:3306/votetunes"
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
NEXT_PUBLIC_RAZORPAY_KEY="rzp_test_xxxxxxxxxxxxx"
RAZORPAY_KEY_SECRET="your-razorpay-secret"
# Pusher Real-Time credentials (optional, falls back to polling if empty)
PUSHER_APP_ID="your-pusher-app-id"
NEXT_PUBLIC_PUSHER_KEY="your-pusher-key"
PUSHER_SECRET="your-pusher-secret"
NEXT_PUBLIC_PUSHER_CLUSTER="your-pusher-cluster"npx prisma db pushnpm run devOpen http://localhost:3000 in your browser.
project/
├── app/
│ ├── api/
│ │ ├── streams/
│ │ │ ├── route.ts # GET list + POST add to queue
│ │ │ ├── playnext/ # Advance queue (priority or regular)
│ │ │ ├── upvote/ # Vote up
│ │ │ └── downvote/ # Vote down
│ │ ├── create-order/ # Razorpay order creation
│ │ ├── verify-payment/ # Razorpay payment verification
│ │ └── auth/ # NextAuth route handler
│ ├── components/
│ │ ├── StreamView.tsx # Main stream view (creator + audience)
│ │ ├── Header.tsx # Nav with auth state
│ │ └── StreamComp/
│ │ ├── StreamPlayer.tsx # yt-player embed
│ │ ├── VideoSubmissionCard.tsx # Submit a song
│ │ ├── PriorityQueueCard.tsx # Paid priority lane
│ │ ├── VideoQueueCard.tsx # Regular voted lane
│ │ ├── ShareStreamCard.tsx # Share link button
│ │ └── streamTypes.ts # Shared TypeScript types
│ ├── dashboard/ # Creator's personal stream page
│ ├── creator/[creatorId]/ # Audience-facing stream page
│ ├── lib/
│ │ ├── auth.ts # NextAuth config
│ │ └── db.ts # Prisma client singleton
│ └── utils/
│ └── razorpay.ts # Payment flow helper
├── prisma/
│ └── schema.prisma # MySQL schema
└── .env # 🚫 gitignored
MIT — fork it, build on it, make it yours.