Discover which artists to see at a music festival based on what you already listen to.
Paste a festival lineup URL, connect Spotify, and Stage Coach scrapes the lineup, scores every act against your listening history, and builds you a Spotify playlist of the best matches — a mix of artists you follow and new ones worth checking out.
| Step | What happens |
|---|---|
| 1. Lineup | You paste a festival lineup URL. A headless Chromium (Playwright) loads the page, and Claude extracts the festival name and the full artist list from the page text. |
| 2. Tastes | You connect Spotify via OAuth. Stage Coach reads your top artists (short + medium term) and top tracks. |
| 3. Match | Each festival artist is looked up on Spotify and given an affinity score. The top ~30 are shown, ranked. |
| 4. Recommendations | A public Spotify playlist is created with 3 tracks per artist and the link handed back to you. |
Each festival artist accumulates points:
| Signal | Points |
|---|---|
| In your short-term top artists | +100 |
| In your medium-term top artists | +60 |
| Appears on one of your top tracks | +40 |
| Per shared genre with your taste profile | +5 |
Tracks are drawn first from songs already in your history (where the artist is primary), then filled from the artist's Spotify catalogue. URIs are de-duplicated across the whole playlist.
- Backend — FastAPI, spotipy, Anthropic SDK
- Frontend — single-page, vanilla JS + Alpine.js + Tailwind (both via CDN)
- Scraping — Playwright (Chromium)
- Store — Redis (cookie-based sessions + a 24 h cache of Spotify lookups)
cp .env.example .env
# then edit .env and fill in your keys| Key | Where to get it |
|---|---|
SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET |
Spotify developer dashboard → your app → Settings |
SPOTIFY_REDIRECT_URI |
http://127.0.0.1:8000/api/auth/callback |
ANTHROPIC_API_KEY |
console.anthropic.com (used for artist extraction) |
REDIS_URL |
redis://redis:6379 under Docker, redis://localhost:6379 otherwise |
SESSION_SECRET |
any random string |
In the Spotify dashboard, add http://127.0.0.1:8000/api/auth/callback to
your app's Redirect URIs and save. Use 127.0.0.1, not localhost — Spotify
only allows plain http:// for loopback IP literals and rejects http://localhost.
Then open the app at http://127.0.0.1:8000 (the session cookie is host-scoped).
docker compose upThen visit http://127.0.0.1:8000.
pip install -r requirements.txt
playwright install chromium
redis-server &
uvicorn backend.main:app --reloadpip install -r requirements.txt
pytest tests/Tests are fully mocked — no network calls or real browser.
backend/
main.py FastAPI app, router wiring, static mount
config.py env-driven settings (pydantic-settings)
scraper.py Playwright page fetch + Claude artist extraction
spotify.py spotipy wrappers (search, top tracks, playlist create)
scoring.py taste profile + affinity scoring + track selection
session.py Redis-backed cookie sessions
cache.py sync Redis cache for Spotify lookups
routers/ /api/scrape, /api/auth, /api/analyze, /api/playlist
frontend/
index.html single-page UI (Alpine.js)
app.js step state machine + fetch calls
style.css spinner + scrollbar
tests/
test_scraper.py
