Phonq is a free, open-source music streaming platform built for the phonk community. Stream hundreds of thousands of Creative Commons tracks — legally, in full, forever free.
Phonq streams the entire Jamendo catalog (500K+ CC-licensed tracks) with:
- A real music player — full-length streaming, a live waveform visualizer (Web Audio API), a persistent queue with drag-to-reorder, shuffle, repeat and volume control
- Live discovery — trending phonk charts and fresh drops straight from the API, plus genre radios
- Full-catalog search — tracks, artists, albums, tags and BPM
- Your library — favorites, playlists and listening history that sync across devices via Google OAuth 2.0
- Artist and album pages — full discographies, bios, similar-artists recommendations and album metadata (cover art, release date) built from a live to DB to static fallback
- Personalized recommendations — tracks surfaced from your listening history, favorite subgenres and similar artists
- Zero ads, zero paywalls — and legally free downloads where the artist allows
And it's 100% open source under the MIT license. Fork it, audit it, self-host it, or build on it.
The gallery below is filled with real captures from the App. Drop your own
docs/screenshots/*.png in and link them here.
| The App | Landing Page |
|---|---|
![]() |
![]() |
Short GIFs of the live waveform / queue help too — see Contributing → Screenshots.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript 5.9 |
| Styling | Tailwind CSS 4 (OKLCH phonk-purple theme) |
| Auth | Auth.js v5 (NextAuth) + Google OAuth 2.0 + email magic links |
| Database | Neon PostgreSQL via Prisma 7 (driver adapter) |
| Music | Jamendo API — CC-licensed tracks, cached in Postgres with a static fallback snapshot |
| Deploy | Vercel (serverless, ready) + Docker for self-hosting |
| Testing | Vitest (unit + API route tests) |
phonq/
├── prisma/
│ ├── schema.prisma # Users, playlists, favorites, listens
│ ├── seed.ts
│ └── migrations/
├── src/
│ ├── app/
│ │ ├── (marketing)/ # Public site: /, /login, product, resources, company, legal
│ │ ├── app/ # Authenticated app: /app/home, search, library, playlists…
│ │ └── api/ # Route handlers (/api/tracks, /api/me/*)
│ ├── components/
│ │ ├── ui/ # Button, Card, Dialog, DropdownMenu, Slider…
│ │ ├── player/ # PlayerContext, PlayerBar, QueuePanel, Waveform
│ │ ├── track/ # TrackCard, TrackRow, LikeButton, AddToPlaylist
│ │ └── layout/ # Nav, Footer, AppSidebar, AppHeader
│ ├── content/ # Marketing content (features, FAQ, legal, blog…)
│ ├── lib/ # jamendo client, auth, prisma, rate-limit, api helpers
│ └── generated/prisma/ # Prisma client (generated — don't edit)
See ARCHITECTURE.md for the full technical design.
- Node.js 20+ (built and tested on 24)
- A free Neon PostgreSQL database
- A free Jamendo client_id (register an app)
- A Google OAuth client ID + secret
# 1. Install dependencies
npm install
# 2. Configure environment
cp .env.example .env
# fill in DATABASE_URL, JAMENDO_CLIENT_ID, AUTH_SECRET,
# AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET, NEXT_PUBLIC_APP_URL
# 3. Create the database schema
npx prisma migrate dev
# 4. Run the dev server
npm run dev # → http://localhost:3000Jamendo client_id: Phonq cannot ship with a working public key — Jamendo suspends shared test keys. Create your own (free, 2 minutes) at devportal.jamendo.com. Without one, the app degrades gracefully: it serves whatever is cached in Postgres, then a bundled static snapshot, and surfaces a friendly "catalog is refreshing" message instead of a raw API error.
YouTube key (optional): set
YOUTUBE_API_KEYto enable the hybrid catalog. Jamendo stays the default (legal, direct audio, no quota), and YouTube fills genre gaps — e.g. Brazilian funk — with tracks played through the YouTube IFrame Player API. Searches are cached in Postgres (youtube_video_mappings), so the 100 searches/day free budget lasts indefinitely once the catalog is seeded. See .env.example.
| Script | Description |
|---|---|
npm run dev |
Start the dev server (Turbopack) |
npm run build |
Generate Prisma client + production build |
npm run start |
Serve the production build |
npm run lint |
ESLint |
npm run typecheck |
tsc --noEmit |
npm test |
Run the Vitest suite |
npm run sync:featured |
Refresh the static fallback snapshot with real Jamendo data |
npm run sync:youtube |
Bulk-seed a genre from a YouTube playlist (playlistItems.list) |
npm run db:generate |
prisma generate |
npm run db:deploy |
prisma migrate deploy |
npm run db:studio |
Open Prisma Studio |
The repo ships a docker-compose.yml that runs the app with a local Postgres — no
Neon, no cloud, no cost:
cp .env.example .env # pre-wired to the local Postgres already
docker compose up --build
# → http://localhost:3000The first boot runs the migrations automatically and seeds the schema. See .env.example for every variable.
One-click deploy (prompts for the same env vars documented below):
Or manually:
- Push this repo to GitHub and import it in Vercel.
- Add the same env vars as
.envin Project → Settings → Environment Variables. - Deploy. Run
npx prisma migrate deployonce (via a Vercel build step or locally) to create the tables.
Phonq runs on free tiers and stays free forever:
- Music — the Jamendo API is free for non-commercial use; tracks are streamed straight from their CDN (never through our servers).
- Database — Neon's free tier easily covers the catalog cache and user library.
- Hosting — Vercel's free tier (or your own Docker/Postgres box).
- We never sell ads or data. If you want to keep the lights on and the features coming, sponsoring is the best way to help:
Contributions are welcome — docs, translations, bug fixes, features. See CONTRIBUTING.md, the Code of Conduct, and the security policy. In short:
git clone https://github.com/hexsyro/Phonq
cd Phonq && npm install
# make your changes…
npm run lint && npm run typecheck && npm testQuestions and ideas are welcome on GitHub Discussions.
MIT — see LICENSE. Music is licensed by its artists under Creative Commons via Jamendo; Phonq does not own the catalog.
Built with ❤️ for the phonk community · @hexsyro

