A real-time song request system for DJs. Guests scan a QR code to submit requests. DJs manage everything from a live dashboard with automatic track detection from their equipment via plugins for Denon, Pioneer, Serato, and Traktor.
Song Management: request queue with BPM/key/genre metadata, accept/reject, song suggestions
Event Management: kiosk controls, bridge status with admin commands, cloud provider sync
Guest join page: scan a QR code, browse the queue, request a song
Guest experience
- QR code join, no app install or login required
- Search songs via Spotify, submit requests with notes, upvote others
- Live request queue and kiosk display showing what's playing now
- Cloudflare Turnstile human verification (invisible managed challenge) on
/joinand/collect - Nickname gate (profanity filter + letter-padding bypass protection) on standard events, or frictionless join — when the DJ enables it, guests skip the nickname/email step and get an auto-generated name they can rename later (great for weddings and private parties)
- Email verification with one-time codes (Resend API) and cross-device guest profile merge
- Pre-event song collection (
/collect) — guests vote on suggestions before the night, DJs bulk-review - Inline song preview in the collect detail sheet (Spotify/Tidal embed)
- Verified badge next to email-verified nicknames in request lists and leaderboard
- Tower v2 UI on
/joinand/collectwith banner art, song detail panels, and vibes enrichment
DJ dashboard
- Accept, reject, and manage requests in real-time (SSE push updates)
- Tabbed event detail with Song Management and Event Management views
- Search Spotify, Beatport, and Tidal directly from the dashboard
- Inline audio previews for Spotify and Tidal tracks
- Color-coded Camelot key badges and BPM proximity indicators for harmonic mixing
- Single-active playing constraint (marking a new track auto-transitions the previous one)
- Multi-service playlist sync to Tidal and Beatport with version-aware matching
- Manual track linking when auto-match fails
- Event banners, play history with source badges, CSV export
- "Enrich All" advanced action to backfill BPM/key/genre on existing requests in batches
- Pre-event collection toggle per event (enable guest voting before doors open)
- Frictionless-join toggle per event (skip the guest nickname/email gate, auto-name guests), with a per-DJ account default applied to new events
- Collection suggestions sync to a dedicated pre-event Tidal playlist; bidirectional option auto-rejects requests removed from the playlist
- Self-service account management: DJs can update their own password and email address
- Bridge connection status, activity log, contextual help system
- Cloud provider OAuth (Tidal, Beatport) with per-event playlist sync toggles
Song recommendations
- Three modes: From Requests (musical profile), From Playlist (template), AI Assist (natural language via Claude)
- Scored on BPM compatibility, harmonic key, genre similarity, and artist diversity
- Half-time BPM matching, junk filtering, MusicBrainz artist verification badges
- Background metadata enrichment via ISRC matching, Beatport, Tidal, MusicBrainz, Soundcharts
Admin dashboard
- User management with role-based access (admin/dj/pending) and self-registration
- Integration health dashboard with per-service enable/disable toggles
- AI/LLM settings, search rate limits, system settings (all DB-backed, no restart needed)
- Human verification enforcement toggle (soft mode for rollout, hard mode post-rollout)
Security & identity
- Fernet-encrypted OAuth tokens at rest (MultiFernet for key rotation)
- Supply-chain hardening: all GitHub Actions pinned to commit SHAs, committed lockfiles (
uv.lockat CVE-floor versions,package-lock.json), CI security scans (bandit, pip-audit, npm audit), and a SHA-digest-pinned base image in the bridge build - Separate public codes for pre-event collection (
/collect) and live join (/join); guest-facing endpoints never expose internal event IDs - IP-free guest identity (cookie + ThumbmarkJS reconciliation, no IP storage or logging)
- HMAC-signed
wrzdj_humancookie with 60-min sliding window after Turnstile pass - IP-bound nonce flow for kiosk-pair (no Turnstile on input-less Pi devices)
Kiosk display
- Full-screen three-column layout: Now Playing, Up Next, Recently Played
- QR pairing with session persistence across power cycles
- Custom banner backgrounds, built-in request modal with touchscreen keyboard, display-only mode
- Raspberry Pi deployment with WiFi captive portal and crash recovery watchdog
Stream overlay
- Transparent OBS browser source at
/e/{code}/overlay - Now Playing track with album art, queue with vote counts
Bridge (DJ equipment detection)
- Plugin system: Denon StageLinQ, Pioneer PRO DJ LINK, Serato DJ, Traktor Broadcast
- Automatic request matching via fuzzy search, Spotify album art enrichment
- Circuit breaker, reconnection with backoff, track buffer replay
- Upstream dependency contract testing with weekly drift detection CI
- Desktop app (Windows/macOS/Linux) or CLI
[Guests] [DJ]
| |
| scan QR | dashboard
v v
[Next.js Frontend] <------> [FastAPI Backend] <--- [PostgreSQL]
| |
+---------+----------+---------+
| | | | |
[Spotify] [Tidal] [Beatport] [MusicBrainz] [Soundcharts]
(search) (sync + (sync + (genre + (discovery +
search) search) verification) BPM/key)
^
| HTTP (API key auth)
|
[Bridge Service]
(plugin system)
/ | | \
StageLinQ PRO DJ LINK Session Icecast
(LAN) (Ethernet) (file) (local)
| | | |
[Denon CDJs] [Pioneer CDJs] [Serato] [Traktor Pro]
| Service | Stack | Directory |
|---|---|---|
| Backend | Python, FastAPI, SQLAlchemy 2.0, PostgreSQL, Alembic | server/ |
| Frontend | Next.js 16, React 19, TypeScript, vanilla CSS | dashboard/ |
| Bridge | Node.js, TypeScript, plugin architecture | bridge/ |
| Bridge App | Electron, React, Vite, electron-forge | bridge-app/ |
| Kiosk | Raspberry Pi, Cage (Wayland), Chromium, Python stdlib | kiosk/ |
Denon (via StageLinQ) -- SC6000, SC5000, Prime 4/4+, Prime 2, Prime Go, X1850/X1800 mixer
Pioneer (via PRO DJ LINK) -- CDJ-3000, CDJ-2000NXS2/NXS, XDJ-1000MK2, XDJ-700, DJM-900NXS2/750MK2 mixer. Requires Ethernet (same LAN).
Serato (via session file monitoring) -- Serato DJ Pro/Lite, any controller. Reads session files from disk, no network setup needed.
Traktor (via Broadcast) -- Traktor Pro 3/4, any controller with broadcast enabled.
- Docker + Docker Compose
- Python 3.11+
- Node.js 22+
- Spotify Developer Account (for song search)
git clone https://github.com/thewrz/WrzDJ.git
cd WrzDJ
cp .env.example .env
# Edit .env with your Spotify credentials, JWT secret, etc.docker compose up -d db./scripts/setup-hooks.shcd server
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
alembic upgrade head
python -m app.scripts.create_user --username admin --password admin
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000cd dashboard
npm install
npm run dev- API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Dashboard: http://localhost:3000
The bridge connects to DJ equipment and reports "Now Playing" data to the server. It requires a running WrzDJ server (steps 1-6 above).
Desktop app (recommended): Download from Releases (Windows .exe, macOS .dmg, Linux .AppImage). Also available via winget install WrzDJ.WrzDJ-Bridge on Windows.
CLI bridge:
cd bridge
npm install
cp .env.example .env
# Edit .env with your API URL, bridge API key, event code, and protocol
npm startProduction uses a subdomain model: app.your-domain.example (frontend) and api.your-domain.example (backend).
docker compose up --buildSelf-hosters can run pre-built multi-arch images from GitHub Container Registry instead of building from source:
ghcr.io/wrzonance/wrzdj-api— FastAPI backendghcr.io/wrzonance/wrzdj-web— Next.js frontend (the API URL is patched in at container start, so one image works for any domain)
Tags: latest (main), vX.Y.Z / X.Y (release tags), sha-<short> (every commit).
cd /opt && git clone https://github.com/thewrz/WrzDJ.git && cd WrzDJ
cp deploy/.env.example deploy/.env # set WRZDJ_VERSION (default: latest) and secrets
./deploy/deploy-ghcr.sh # pulls images, restarts the stack, polls /healthdeploy/docker-compose.ghcr.yml runs db + api + web straight from the registry (no --build); deploy/deploy-ghcr.sh [VERSION] is the one-command pull-and-restart helper.
Render auto-detects render.yaml. Push to GitHub, connect to Render, set credentials in the Environment tab.
Railway: Create project on Railway, add PostgreSQL, deploy server/ and dashboard/ as separate services.
cd /opt && git clone https://github.com/thewrz/WrzDJ.git && cd WrzDJ
cp deploy/.env.example deploy/.env # Fill in secure values
docker compose -f deploy/docker-compose.yml up -d --buildSet up nginx:
APP_DOMAIN=app.yourdomain.com API_DOMAIN=api.yourdomain.com ./deploy/setup-nginx.sh
sudo certbot --nginx -d app.yourdomain.com -d api.yourdomain.comGoAccess analytics are available for production traffic — see deploy/scripts/analytics.sh.
See deploy/DEPLOYMENT.md for full setup instructions.
ENV=production
DATABASE_URL=<PostgreSQL connection string>
JWT_SECRET=<openssl rand -hex 32>
TOKEN_ENCRYPTION_KEY=<openssl rand -hex 32>
SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET
TIDAL_CLIENT_ID / TIDAL_CLIENT_SECRET
BEATPORT_CLIENT_ID / BEATPORT_CLIENT_SECRET
BRIDGE_API_KEY=<openssl rand -hex 32>
ANTHROPIC_API_KEY=<optional, enables AI Assist recommendations>
TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY # Cloudflare Turnstile (human verification + DJ self-reg)
HUMAN_COOKIE_SECRET=<openssl rand -base64 32> # signs wrzdj_human cookie
RESEND_API_KEY # email verification provider
EMAIL_FROM_ADDRESS=noreply@send.yourdomain.com
SOUNDCHARTS_APP_ID / SOUNDCHARTS_API_KEY # discovery API
LISTENBRAINZ_USER_TOKEN # optional, ListenBrainz artist discovery for recommendations
CORS_ORIGINS=https://app.yourdomain.com
PUBLIC_URL=https://app.yourdomain.com
Interactive API docs are available at /docs when the backend is running.
WrzDJ/
server/ # FastAPI backend
dashboard/ # Next.js frontend
bridge/ # DJ equipment bridge (Node.js)
bridge-app/ # Electron desktop app for the bridge
kiosk/ # Raspberry Pi kiosk deployment
deploy/ # Production deployment configs
scripts/ # Git hooks and dev tooling
.github/workflows # CI, release, and dependency health pipelines
MIT