Skip to content
← Back to projects
WebTunes icon

WebTunes

A self hosted music streaming platform: upload your own library, stream it in any browser, and share it with friends.

Try it with a demo account

Open the live app and sign in with one of these shared demo accounts. Each comes with a seeded royalty free library, and the two accounts are already friends, so you can see library sharing in action.

  • demo1@demo.demoDemo1
  • demo2@demo.demoDemo2

WebTunes is a full stack music streaming platform that I designed, built, and deployed to production. A user uploads their personal music library to object storage and streams it from any browser, with fast search, playlists, friend based sharing, and full offline support. It runs live on a VPS today.

A core design goal was keeping the application server out of the data path. Audio never flows through the server: the browser receives a short lived presigned URL and streams each file directly from S3 compatible storage using HTTP range requests, which keeps seeking instant and the server light. The same model backs offline playback.

Search and library

  • Full text search across titles, artists, albums, and lyrics, powered by a weighted PostgreSQL tsvector with a GIN index for fast, ranked results.
  • Metadata and cover art are extracted automatically from uploaded files using their ID3 and Vorbis tags, with a filename fallback when tags are missing.
  • Duplicate uploads are caught by content hash, so the same file is never stored twice.
  • Lyrics come from embedded tags, falling back to the LRCLIB API when a track has none.

Streaming and storage

  • Direct browser to storage streaming over presigned URLs, so the application server never proxies audio bytes.
  • HTTP range requests give instant seeking within a track.
  • Storage is S3 compatible: Cloudflare R2 in production and MinIO in local development, with one storage layer behind both.

Sharing and access control

  • Friend requests with accept and decline. Accepted friends can browse and play each other's non private libraries.
  • A single access rule is enforced consistently across listing, streaming, search, and playlists, so visibility cannot drift between features.
  • Playlists support ordered tracks and public or private visibility.

Offline and PWA

  • Installable progressive web app backed by a service worker.
  • A download manager queues tracks and playlists for offline playback, stored in IndexedDB, with storage quota tracking.
  • Cached audio is served with range aware responses so offline playback works correctly, including on iOS.

Accounts and security

  • Email and password accounts with required email verification and password reset, built on Auth.js with database backed sessions.
  • Authentication endpoints are rate limited per email and per IP address.
  • Request payloads are validated with Zod, and a strict content security policy is applied across the app.

Tech stack

Built with Next.js on the App Router, React, and TypeScript, on PostgreSQL with Drizzle ORM, Auth.js, and the AWS SDK for S3 compatible storage. Client state runs on Zustand, transactional email on Resend, local services on Docker, and it is deployed as a systemd service behind Caddy.