I worked on this project for a couple weeks before starting at APT (almost two years ago now). I saw a reddit thread for a website that curates playlists based on artists touring to cities for concerts and I figured that I could program something similar to create pretty good playlists without the manual curation.

The flow: users log in with Spotify, input constraints for their playlist (genre, location, timeframe, concert radius), hit submit, and a playlist is created.

hear now homehear nowspotify playlist

The front end uses JavaScript (a bunch of JQuery) and Flask (a lightweight Python web framework).

I used Google Maps to embed a map on the generate page. It is was nice to use, straightforward to zoom, drop a pin, style the map, etc. I did have one issue with the Maps API: the autocomplete was not debounced, so with some really heavy testing I was hitting the free API limit sometimes. It sounds like Google has since changed the pricing structure for their autocomplete service to be session-based rather than request-based which should give me more leeway here, but I haven’t gotten around to updating my code.

The back end uses Python with Celery (a job queue library) to manage the relatively long-running playlist generation jobs. The basic back end flow is:

  • Use SeatGeek’s API to find venues/artists near the user.
  • Use Spotify’s API to search for artists, and use fuzzy matching between search results and artist names to map them to Spotify’s artist IDs.
  • Use Spotify’s API to get the top 5-10 most popular tracks for each artist, randomly select ~30 to add to a playlist.

Spotify’s search API isn’t a batch API, which is the main bottleneck on playlist generation time. The app has to make many search requests which are relatively expensive. I ended up using Redis to cache API calls (i.e. for the artist name to ID mapping) which significantly improved performance, but I don’t get much traffic so the cache is usually pretty cold. 😅

The app is split up with containers (‘web’, ‘worker’, and ‘redis’) for organization, to make it easier to deploy, and to make these separately scalable (but I haven’t had enough traffic to worry about this last point).

Website is here.

Last aside: I’m usually bad at taking photos but I took the background picture on the homepage of the app and I’m kind of proud of it. :)