Back to Blog
Loading music data...

building a Personal Live Spotify Player

5 min read

ever landed on someone's personal site and wondered what tunes they vibe to while coding or chilling? yeah, same. spotify lets you build apps to showcase your currently playing music—but there's a huge catch: visitors usually have to log in to spotify just to view it. honestly, nobody wants to do that just to peek at someone else's playlist.


i wanted something clean and simple—zero friction, no visitor logins, just my personal live playlist displayed seamlessly. after messing around with apis and serverless architecture, i finally found a neat solution.


here's exactly how i pulled this off using next.js, vercel's cron jobs, and their handy kv storage.

the problem: spotify's oauth hassle

typically, embedding spotify data on your site looks like this:

  1. visitor arrives at your site.
  2. clicks "login with spotify."
  3. redirected to spotify's auth page.
  4. visitor logs into spotify and approves access.
  5. finally, sees what music you're playing.

way too many steps, right? all i wanted was to let visitors see my live listening data without forcing them to log in or jump through oauth hoops. plus, i couldn't use public apis because spotify doesn't offer a way to publicly expose live playback without oauth.


so, here's how i got around that pesky oauth limitation:

my solution: vercel cron + kv (serverless ftw)

instead of making each visitor authenticate individually, i found a workaround where i authenticate just once myself, and then regularly update and store the data server-side. visitors never have to log in, yet they still get a nearly real-time view of my spotify playback.

the whole thing runs like this:

1. authenticate once (just me)

  • i created a protected admin route (/api/admin/spotify-auth-example) with a secure password.
  • visited the route once, authenticated with spotify, and got back a refresh token.
  • stored that token securely using vercel kv (like redis but serverless).

here's what storing the tokens looks like in code:

await kv.set('admin_spotify_access_token', data.access_token, { ex: data.expires_in });
await kv.set('admin_spotify_refresh_token', data.refresh_token);

after this initial step, i never have to authenticate again manually unless something breaks.

2. cron job updates (every 30 mins)

vercel's cron job triggers my next.js serverless function every half-hour, automatically refreshing my token if necessary and fetching the latest playback data.

here's the vercel cron setup (in vercel.json):

{
  "crons": [
    {
      "path": "/api/cron/example-endpoint",
      "schedule": "*/30 * * * *"
    }
  ]
}

the cron job updates my current playback and also records recent tracks, which gives visitors some cool insights into my music taste over time.


Vercel Cron Job Logs showing successful execution

here's how i handle different responses from spotify (like when i'm not playing anything):

if (spotifyResponse.status === 204) {
  await kv.set('spotify_playback_data', {
    is_playing: false,
    timestamp: Date.now(),
    item: null
  });
}

3. visitor view (zero auth required)

on my website, visitors press 'M' to see what's playing. this triggers a call to an endpoint that simply fetches cached data from kv storage. no spotify api calls, no oauth, just clean and fast.

this ensures that visitors immediately see my current playback state (song name, artists, album art, progress bar) with zero friction.

technical challenges (and fun bits)

while straightforward in theory, building this taught me a ton about managing oauth tokens and handling edge cases in a serverless environment. some challenges i tackled:

  • refresh tokens:
    spotify's access tokens expire every hour, so the cron job logic had to manage token refreshing seamlessly.
  • cron endpoint security:
    i had to ensure the cron job endpoint was secure, allowing only vercel's cron to trigger it, but also permitting manual testing:
if (!userAgent.includes('vercel-cron') && password !== ADMIN_PASSWORD) {
  return res.status(401).json({ 
    error: 'Nice try, but don\'t ruin the fun',
    message: 'This cron job is automated magic. No peeking behind the curtain!' 
  });
}
  • state management (kv storage):
    using kv to store tokens and playback state meant i had a globally accessible and reliable data store, making serverless functions practical and efficient.

Vercel KV storage showing Spotify track history and tokens
  • data freshness and accuracy:
    it was essential to show visitors how "fresh" the data was and adjust playback progress dynamically based on how old the cached data is:
const getAdjustedProgress = () => {
  if (!playbackState?.item?.progress_ms || !playbackState.is_playing || !playbackState._meta) {
    return playbackState?.item?.progress_ms || 0;
  }
  
  // If song is playing, adjust progress based on how old the data is
  const originalProgress = playbackState.item.progress_ms;
  const dataAgeMs = playbackState._meta.data_age_seconds * 1000;
  const adjustedProgress = originalProgress + dataAgeMs;
  
  // Make sure we don't exceed the song duration
  return Math.min(adjustedProgress, playbackState.item.duration_ms);
};

why this setup rocks

this method genuinely solves a niche but very real problem. spotify doesn't provide a straightforward api to publicly expose live playback without oauth. the common alternative—last.fm—only provides playback history without live data or progress.

plus, it leverages powerful serverless tech:

  • vercel edge functions for instant serverless apis.
  • vercel kv for simple, global storage.
  • vercel cron for scheduled updates.
  • next.js for quick api endpoints and ui integration.

all of this runs without any servers to maintain, scaling effortlessly with minimal cost (usually within vercel's generous free tier).

result: a clean personal touch

now, visitors to my site can casually check out what i'm vibing to anytime. press 'M', and they instantly see my current track info:


Live Spotify player showing my currently playing track
  • album art
  • track title and artists
  • live(ish) progress bar
  • indicators for playback status (playing, paused, or offline)
  • a history of recently played tracks for context

this small feature adds personality to my website and honestly, it's been a fun side project that deepened my knowledge of modern web stacks.

want your own version?

here's what you'll need to build something similar:

  • spotify developer account
  • vercel account with kv and cron enabled
  • next.js (for frontend and backend)
  • basic understanding of oauth 2.0

if you're interested in building your version, feel free to reach out! i'm always happy to share more insights or even help debug a tricky oauth flow.


next time you visit, press 'M' to check out my playlist. You might discover your next favorite song, or just see what weird music I listen to late at night!


happy hacking!