Adding a Spotify "Now Playing" widget to your Jekyll site
10 June 2020
I recently added a widget to my homepage that shares what I’m currently playing on Spotify. It looks like this:
[The above is just a static example. But if I am listening to something right now, you can see it on my homepage.]
Adding this simple line was more complicated than I had first anticipated, given that this site is made using Jekyll - a static site generator. Also, I didn’t want to use any client-side code.
1. Getting your Spotify credentials
To interact with the Spotify API you will need to get yourself a client_id
and client_secret
.
First, create a new application through the developer dashboard. You’ll have to log in with your Spotify account to get here. Then click “My New App” and fill in the details.
Then click through to your application to get them:
2. Authorising yourself
The next step is to go through a one-time OAuth dance. This will give you both an access_token
, lasting one hour, and a refresh_token
, which will let you continously update your access_token
once it expires.
There are 3 different flows for authorising yourself with Spotify, depending on your needs.
Long-story short for this widget: because you are accessing a specific user’s data (i.e. yours) you need to go through the Authorization Code Flow -- unfortunately, the longest one:
From Spotify’s docs. It’s a... complicated dance.
To kick things off you need to construct an authorisation URL to visit in your browser. This will let you log in and tell Spotify that you’re giving this newly-created application the thumbs up to access your user data. 👍
The endpoint you need for this widget is documented here. You need to include the user-read-currently-playing
scope when constructing the URL.
In an irb
console:
Important -- Whilst the value of redirect_uri
doesn’t matter in terms of functionality, be aware that you will be redirected to it with sensitive details appended. So ideally you should own the domain to avoid it appearing in someone else’s logs.
You must also add the exact same redirect_uri
value to your application’s settings:
If you now grab the authorisation URL and visit it in your browser, you are asked to log in to Spotify (if you aren’t already) and agree.
Then the redirect URI kicks in and takes you to https://edforshaw.co.uk/callback?code=VERY_LONG_CODE
.
Copy this VERY_LONG_CODE
from the URL. This is known as the authorization code.
Note -- this is not the access_token
or refresh_token
. You now need to request those using this code. The dance goes on... 💃
Back in irb
again:
You finally have your access_token
and refresh_token
.
Thankfully that is a one-time manual job, and the fun can now begin.
3. Getting your current playing song
Now fire up a song on Spotify and hit the currently playing endpoint:
After parsing the response data you now have your current playing track name and artist. 😎
The remaining steps are specific to my Jekyll site.
4. Adding the widget
On my homepage I use a Jekyll include for this widget, which lives in _includes/now_playing.html
:
...
{% include now_playing.html %}
pages/index.md
This include is empty initially - but I have a separate template with liquid tags, which I will use to render content for it:
_includes/now_playing.html.template
On my blog’s server I have the following process running in the background:
JEKYLL_ENV=production jekyll build --watch --incremental > /dev/null 2>&1 &
This process watches for updates to my Jekyll project - meaning that every time I update _includes/now_playing.html
, any page that use this include will be rebuilt (and only these pages, thanks to the --incremental
flag).
Now all that remains is for me to update _includes/now_playing.html
whenever I start or stop playing a song, and everything should Just Work.
5. Updating the widget
In a perfect world, every time I hit play/pause on Spotify it would trigger a webhook to my server, allowing me to update my widget only when I need to.
Sadly, webhooks for player events are not yet supported by the API [although they are apparently high priority].
Therefore, I have to poll for changes at a suitable time interval. I decided on 30 seconds.
Firstly, I tidied up the earlier code into a single Ruby file, with some additions:
tasks/spotify_nowplaying.rb
A few notes about this:
- The refreshing of the
access_token
is handled in the event of the access token expiring and receiving a 401 (Unauthorized) response. - If there is no response body, or the current song is paused, or if a podcast is being played rather than a song - the include file is emptied and the widget displays nothing.
- I added a YAML config file in my home directory to store all of my Spotify credentials. This also gives me somewhere to persist the
access_token
whenever it gets updated.
~/.spotify_nowplaying.yml
- Songs with multiple artists are stitched together with an &.
- Sub-strings of song titles containing “Remastered” are thrown away to keep things clean.
- The song ID is used to construct a Spotify link for the icon.
And finally, on the server we add a cron task to run this ruby file every 30 seconds:
Cron’s minimum unit is one minute, hence the sleep 30 workaround.
And we’re done. All that for one line. Totally worth it, of course. 😅
Possible future improvements:
- Show the album cover of the current song.
- Make the Spotify logo pulse to the song’s tempo.
- Use webhooks, or even websockets, when the API supports it.