writing — june 2026 · 4 min
Putting my Spotify on the page, without overdoing it
When I'm listening to something, a small line shows up at the bottom of this site with the track. It's a tiny thing, and that's the point. What I want to write about is the little bit of backend behind it, and the parts I decided not to build.
01The line
It shows what I'm playing on Spotify, and nothing more. When I'm not listening, the footer looks exactly like it always does, with no empty slot left behind. When a track is on, a quiet line fades in: a little equalizer, the song, the artist. The first time you reach the footer it spells out “listening to” so you know what it is, then it tucks that label away and leaves just the bars and the song. No album art down there, no panel. It's meant to be noticed once and then ignored.
02The shape
Spotify won't let the browser ask “what is Ammar playing” on its own, and it shouldn't, because that would mean putting a secret in the page where anyone could read it. So there is one small server step in the middle.
- browserpolls /api/now-playing every 20s
- route handlertrades a refresh token for a one-hour access token
- spotifyreturns the currently-playing track
- footerthe line fades in, or stays hidden
The browser polls a single endpoint every twenty seconds. That endpoint runs on Vercel, in the same project as the site. It holds a refresh token, trades it with Spotify for an access token that lasts an hour, asks what's currently playing, and hands back a few fields: the title, the artist, a link. If nothing's on, it says so and the footer stays quiet.
The refresh token is the whole trick. You log in to Spotify once, by hand, and get a token that doesn't expire. After that the server can quietly swap it for a fresh hour-long access token whenever it needs one, with no login screen and no secret ever reaching the browser.
03The choice
I already had somewhere I could have put this. The visitor counter at the bottom of the site is a real AWS backend, with Lambda and Terraform and a deploy pipeline. I could have added a Spotify endpoint to it, or stood up a separate little service just for this.
I didn't, because this is a read-through proxy and that would have been too much. A route handler on Vercel lives in the same project as the site, so there's nothing separate to deploy, no cross-origin setup, and the secret is just an environment variable. It was the smaller option and it was the right one. I wrote about the opposite call in the counter piece, where I deliberately built far more than the job needed, to practice the full setup. The skill is knowing which situation you're in.
04Caching
Two bits of caching do the real work, and neither depends on where the code runs. The access token is good for an hour, so the server keeps it between requests instead of asking Spotify for a new one every time. And the response itself is cached at Vercel's edge for a few seconds, so if a handful of people are on the site at once they share one answer rather than each hitting Spotify. The polling is what makes it feel live; the caching is what keeps it from being wasteful.
05Closing
So this is the counter's mirror image. There I wrapped a number that barely matters in remote state, federated login, and infrastructure-as-code. Here I had a feature that could have justified all of that, and kept it to one file and an environment variable instead.
Both felt right, for the same reason: spend about as much as the job is worth. The counter was a reason to build the whole pipeline. This was a reason to build almost nothing. Same judgment, pointed the other way.