Deejay is a local-first song request app for private events.
It gives attendees a tiny request surface, resolves messy song text with AI, searches Spotify, and queues the selected track from the host computer. It also includes a Spacebase1 intent-space flow where humans or agents post song-request intents, wait for Deejay promises, accept or revise them, and observe completion.
This is hackathon/demo software, not a production service. It is intentionally small: no attendee accounts, no voting, no moderation queue, and no complex event management.
- Runs a local Express app on the host computer.
- Uses Spotify OAuth and the Spotify Web API to control the host's active Spotify device.
- Uses OpenAI when configured to interpret vague song requests.
- Searches Spotify, chooses a likely track, and queues it after the user or agent accepts the promise.
- Logs recent requests locally.
- Posts and watches Spacebase1 commons acts for the intent/promise/accept/complete demo.
- Exposes an agent doorway so another coding agent can request a song without using the UI.
Requirements:
- Node.js 22 or newer.
- Spotify Premium account.
- A Spotify Developer Dashboard app.
- An OpenAI API key, optional but recommended.
Install and configure:
npm install
cp .env.example .env
npm run doctorFill in .env:
SPOTIFY_CLIENT_IDSPOTIFY_CLIENT_SECRETOPENAI_API_KEY, optional
In the Spotify Developer Dashboard, add this redirect URI exactly:
http://127.0.0.1:5177/auth/spotify/callback
Start the app:
npm run devOpen:
- Attendee UI: http://127.0.0.1:5177/
- Host console: http://127.0.0.1:5177/host
On the host page, connect Spotify, keep the native Spotify app open, and make sure this computer is the active Spotify Connect device.
Spotify OAuth should stay on loopback:
APP_BASE_URL=http://127.0.0.1:5177
SPOTIFY_REDIRECT_URI=http://127.0.0.1:5177/auth/spotify/callback
Attendees do not need to use that loopback URL. Set PUBLIC_EVENT_URL to the URL they should scan or open:
PUBLIC_EVENT_URL=http://192.168.1.23:5177
For a public tunnel or custom domain:
PUBLIC_EVENT_URL=https://deejay.example.com
See docs/DEPLOYMENT.md for LAN, Cloudflare Tunnel, ngrok, and watchdog notes.
/human attendee flow./hosthost console and ready check./agent-setupgenerated agent doorway for the current host URL./deejay-song-request.SKILL.mdgenerated agent skill./deejay-agent-client.mjsstandalone Node helper for clean-room agent runs./agent-instructions.mdstatic agent guide.
Clean-room agent smoke test:
curl -sS http://127.0.0.1:5177/deejay-agent-client.mjs -o /tmp/deejay-agent-client.mjs
node /tmp/deejay-agent-client.mjs "King Kunta by Kendrick Lamar"npm run dev # run with node --watch
npm start # run without watch mode
npm run doctor # check local setup
npm run check # syntax-check server and browser scripts
npm run watchdog:once # one local health/remediation pass
npm run watchdog # keep the local app, and optionally a tunnel, aliveLocal state is written under data/ and ignored by Git:
spotify-token.json: Spotify OAuth token.requests.json: recent request log.settings.json: host settings and generated playlist ID.spacebase-resolver-agent.json: generated Spacebase1 resolver identity/session.*.log: app, tunnel, and watchdog logs.
Do not commit .env, data/, tunnel credentials, or logs.
Start with docs/HACKING.md. The short version:
server/index.jsowns the HTTP API, Spotify integration, AI resolver, request log, and watcher loop.server/spacebase.jsowns Spacebase1 signup, DPoP, ITP framing, scan, and post mechanics for the resolver-agent.public/attendee.jsowns the human intent/promise/accept/revise flow.public/host.jsowns the host console.public/deejay-agent-client.mjsis the standalone clean-room agent helper.
Keep v1 small. The charm is that the flow is visible and hackable, not that it has every event-product feature.