Beatsync is a high-precision web audio player built for multi-device playback. The official app is beatsync.gg.
beatsync-demo.mov
- Millisecond-accurate synchronization: Abstracts NTP-inspired time synchronization primitives to achieve a high degree of accuracy
- Cross-platform: Works on any device with a modern browser (Chrome recommended for best performance)
- Spatial audio: Allows controlling device volumes through a virtual listening source for interesting sonic effects
- Polished interface: Smooth loading states, status indicators, and all UI elements come built-in
- Self-hostable: Run your own instance with a few commands
Note
Beatsync is in early development. Mobile support is working, but experimental. Please consider creating an issue or contributing with a PR if you run into problems!
This project uses Turborepo.
Copy env examples first:
cp apps/client/.env.example apps/client/.env
cp apps/server/.env.example apps/server/.envRun the following commands to start the server and client:
bun install # installs once for all workspaces
bun dev # starts both client (:3000) and server (:1001)Local env defaults:
# apps/client/.env
NEXT_PUBLIC_API_URL=http://localhost:1001
NEXT_PUBLIC_WS_URL=ws://localhost:1001/ws
NEXT_PUBLIC_DEMO_MODE=0
# apps/server/.env
HOST=0.0.0.0
PORT=1001
PROVIDER_URL=
CREATOR_SECRET=Beatsync cannot run fully on Vercel alone because this repo uses a long-lived Bun WebSocket server in apps/server.
Deploy it in 2 parts:
apps/clienton Vercelapps/serveron another host that supports persistent processes and WebSockets Examples: Railway, Render, Fly.io, VPS, or your own machine behind ngrok
Create a Vercel project that points to this repo with:
- Root Directory:
apps/client - Build Command:
next build - Install Command:
bun install - Output Directory:
.next
Set these Vercel environment variables:
NEXT_PUBLIC_API_URL=https://YOUR-BACKEND-DOMAIN
NEXT_PUBLIC_WS_URL=wss://YOUR-BACKEND-DOMAIN/ws
NEXT_PUBLIC_DEMO_MODE=0
NEXT_PUBLIC_POSTHOG_KEY=Important:
NEXT_PUBLIC_WS_URLmust usewss://in production- The backend domain must be reachable publicly
- Do not point Vercel to
localhost
On any machine/server that can keep Bun running:
cp apps/server/.env.example apps/server/.env
cd apps/server
bun install
bun run build
bun run startFor development:
cd apps/server
bun run devThe backend listens on:
HOST=0.0.0.0PORT=1001by default
If you want to test Vercel frontend against your local backend:
Run backend locally:
cd apps/server
bun run devExpose it:
ngrok http 1001Then set Vercel env to the ngrok URL:
NEXT_PUBLIC_API_URL=https://YOUR-NGROK.ngrok-free.app
NEXT_PUBLIC_WS_URL=wss://YOUR-NGROK.ngrok-free.app/wsRedeploy the Vercel project after changing env vars.
Run both apps together:
bun install
bun devOr separately:
cd apps/server && bun run dev
cd apps/client && bun run devOpen:
- Frontend:
http://localhost:3000 - Backend:
http://localhost:1001
502 /wson ngrok usually means nothing is listening on port1001WebSocket upgrade failedusually means the client is hitting the wrong backend URL- If frontend is on HTTPS, WebSocket must be
wss://, notws:// - Vercel env changes require a redeploy
- If uploads/default tracks depend on object storage, update
S3_*values inapps/server/.env
| Directory | Purpose |
|---|---|
apps/server |
Bun HTTP + WebSocket server |
apps/client |
Next.js frontend with Tailwind & Shadcn/ui |
packages/shared |
Type-safe schemas and functions shared between client & server |