TuneVote
Real-time music voting platform I designed, built, and operate end to end — from the Socket.io backend to production architecture, database, and deployment.

TuneVote is a music voting platform: a room votes on what plays next, in real time, and the platform suggests songs to add. I built it independently, end to end — not just the application code, but the production architecture, database, and deployment that keep it running for real users.
The moving parts#
- Real-time voting over Socket.io, so every participant sees the queue update as votes come in rather than on a refresh.
- AI song suggestions through the OpenAI API, to seed and extend a queue when the room runs dry.
- YouTube integration via yt-dlp for resolving tracks.
- Sign-in with Google and Facebook.
Running it in production, not just locally#
Developing TuneVote locally and operating it for real users turned out to be two different problems. Once people were connected to the same live session, I had to reason about the whole thing as production infrastructure, and make the architecture, database, and deployment decisions myself.
Splitting the infrastructure by what actually needs the server. The real-time Socket.io backend needs a persistent, always-on server, so it runs on a VPS. The landing page and frontend do not — serving them from the VPS would only spend its resources on work it does not need to do. So I separated the two: the VPS is dedicated to the real-time backend, and the static frontend is served from dedicated hosting (e.g. Vercel). The result is that the server's resources stay focused on the workload that genuinely requires them.
Finding the real cause of slowness. When the production system got slow, the easy answer would have been "get a faster server." Instead I looked at whether the architecture was loading the VPS with work it should not have been carrying in the first place. Moving the non-essential frontend/landing-page workload off the VPS freed it to concentrate on the real-time backend — an architectural fix rather than a hardware one.
Redesigning the database as part of the system. The initial schema was not well suited to how the app actually used it, so I redesigned it substantially: cutting redundancy, storing information more correctly, distributing load more evenly, and making the common operations more efficient — so the database adds as little avoidable pressure to the overall system as possible as usage grows. Schema changes are handled through Knex migrations rather than by hand.
A test-before-production workflow. Changes go to a test environment first, where the automated tests run against them; only once they pass are they released. Production deploys then run through an automated, AI-assisted process over SSH to the VPS, so shipping a change is repeatable rather than a manual scramble.
The recurring questions were the production ones: what happens when many users share one real-time session, which component is quietly consuming resources, what could become a bottleneck as the app grows, and how to improve the architecture proactively rather than waiting for a production failure to force the issue.
It runs in Docker on a VPS. It's open-source, with a Discord community for feature requests and bug reports, and around 30 active users.
The sub-project that made it work: a YouTube scraping funnel#
TuneVote only feels good if the songs are already there — if a user has to paste a YouTube link every time they want to add a track, the voting loop dies. So a second, separate project grew up alongside it, purely to fill the database in bulk.
It's a Python funnel built on yt-dlp. You feed it a list of artists — one channel after another — and for each one it walks the channel and pulls every video's link. Take Taylor Swift: point the funnel at the channel and it scrapes all of her video URLs, writes them to a text file, and then that text file is matched up and turned into an SQL file that loads straight into TuneVote's database.
The payoff is on the user's side. Because the catalogue is pre-populated this way, when someone searches for a Taylor Swift song it is already in the database and gets recommended and shown — no hunting for the right YouTube link, no pasting. The scraper is invisible to the end user, but it is the reason search actually returns something.
Sub-project stack: Python · yt-dlp · SQL generation → TuneVote database.
Next, have a look at
Weft
A local-first, self-hostable Notion alternative — nested-page block editor, real-time co-editing over Yjs, Git-style version history and a graph view, all in one command.

Sentinel
Dynamic KYC-drift monitor built for AMINA Bank's SwissHacks 2026 challenge — it catches the slow structural changes that quietly invalidate a customer's risk profile.