The following is ai generated, this was meant for my reference, idk why ai is acting like im trying to convince you i wrote this.

How I Implemented the Spotify API

Overview

The goal was to build a “Now Playing” widget that shows what you’re currently listening to on Spotify. To do this, your website needs to talk to Spotify’s API on your behalf — which requires authentication, authorization, and periodic data fetching.


1. How Spotify’s API Works (The Big Picture)

Spotify’s API is a REST API — you make HTTP requests to specific URLs and get JSON back. But before you can do that, Spotify needs to know who you are and that you’ve given permission for the app to read your data.

This is handled by OAuth 2.0, an industry-standard authorization protocol. The basic idea:

  1. You redirect the user to Spotify’s login page
  2. The user logs in and clicks “Agree”
  3. Spotify redirects them back to your site with a temporary code
  4. Your server exchanges that code for an access token (short-lived) and a refresh token (long-lived)
  5. You use the access token to make API calls
  6. When the access token expires, you use the refresh token to silently get a new one

2. The Two Types of OAuth Flows (and Why You Chose One)

There are two main flows for this use case:

PKCE Flow (Client-Side)

  • Runs entirely in the browser
  • No client secret needed
  • Stores tokens in localStorage
  • Good for static sites with no server

Authorization Code Flow (Server-Side) ✅ What you used

  • Runs on the server
  • Uses your Client Secret to exchange codes for tokens
  • Stores the refresh token in a secure httpOnly cookie (invisible to JavaScript)
  • Automatically refreshes the access token silently
  • More secure — secrets never touch the browser

You used the server-side flow because your Astro project has SSR (server-side rendering) enabled, making it the better and more secure choice.


3. Setting Up the Spotify App

Before writing any code, you registered your app in the Spotify Developer Dashboard. This gave you:

  • Client ID — a public identifier for your app
  • Client Secret — a private key used server-side to authenticate your app
  • Redirect URI — the URL Spotify sends the user back to after they authorize (http://127.0.0.1:4321/callback)

These were stored in a .env file and accessed via import.meta.env in Astro — keeping secrets out of your source code.


4. The Authorization Flow Step-by-Step

Step 1: Build the Auth URL (index.astro)

When the user hasn’t connected Spotify yet, you show them a “Connect Spotify” link. That link points to Spotify’s authorization endpoint with these query parameters:

ParameterValuePurpose
client_idYour Client IDIdentifies your app
response_typecodeTells Spotify you want an auth code
redirect_uriYour callback URLWhere to send the user after login
scopeuser-read-currently-playingWhat data you need access to

Scopes are important — they limit what your app can do. You only requested user-read-currently-playing, meaning your app can only read the current track. It can’t control playback, read playlists, etc.

Step 2: Handle the Callback (callback.astro)

After the user clicks “Agree” on Spotify’s page, Spotify redirects them to http://127.0.0.1:4321/callback?code=XXXX.

Your callback.astro page:

  1. Reads the code from the URL
  2. Makes a POST request to https://accounts.spotify.com/api/token with:
    • The code
    • Your Client ID and Secret (base64 encoded in the Authorization header)
    • Your redirect URI (for verification)
  3. Gets back a refresh_token
  4. Saves the refresh token in a secure httpOnly cookie
  5. Redirects the user back to /

The httpOnly cookie is key — it means JavaScript in the browser cannot read it, protecting it from XSS attacks.

Step 3: Fetch Now Playing (api/spotify.ts)

This is a server-side API endpoint that your widget polls every 10 seconds. It:

  1. Reads the refresh token from the cookie
  2. Exchanges it for a fresh access token (access tokens expire after 1 hour)
  3. Calls https://api.spotify.com/v1/me/player/currently-playing
  4. Returns the track name, artist, album art, and Spotify URL as JSON

If nothing is playing, Spotify returns a 204 No Content status — so you handle that case and return { isPlaying: false }.


5. The Widget (Spotify.astro)

The widget is a client-side component that:

  1. Calls /api/spotify (your own server endpoint) on page load
  2. If something is playing, shows the album art, track name, and artist with animated bars
  3. If nothing is playing, shows a fallback message
  4. Repeats every 10 seconds using setInterval

Importantly, the widget never talks to Spotify directly — it talks to your server, which talks to Spotify. This keeps your tokens safe.


6. The Token Lifecycle

User logs in once
        ↓
Spotify gives you a refresh_token (stored in cookie, lasts ~1 year)
        ↓
Every API call: exchange refresh_token → access_token (lasts 1 hour)
        ↓
Use access_token to call Spotify API
        ↓
Repeat silently forever

The user only ever has to click “Connect Spotify” once. After that, the refresh token handles everything automatically.


7. Key Concepts to Remember

REST API — You communicate with Spotify by making HTTP requests (GET, POST) to specific URLs. Responses come back as JSON.

OAuth 2.0 — A standard way to let users grant your app limited access to their data without giving you their password.

Access Token — A short-lived credential (1 hour) you include in API requests as a Bearer token in the Authorization header.

Refresh Token — A long-lived credential you use to get new access tokens without asking the user to log in again.

Scopes — Permissions you request upfront. Only request what you need.

httpOnly Cookie — A cookie the browser stores but JavaScript cannot read. Ideal for storing sensitive tokens.

SSR (Server-Side Rendering) — Your Astro app runs code on the server, which is what allows you to securely handle secrets and cookies.


8. Why Not Just Use the Spotify-Provided Code?

The Spotify docs push the PKCE flow with client-side JavaScript because it works on any static site. But it stores tokens in localStorage, which is readable by any JavaScript on the page — a security risk. Since you have a real server (Astro SSR), the server-side approach is strictly better: secrets stay on the server, tokens stay in secure cookies, and users get a seamless experience.