Now Playing with Spotify API and Next.js API Routes

4 min read

Create a Spotify Application

The first step is creating a Spotify application to retrieve credentials for authentication.

  • Go over to the Spotify Developer Dashboard and log in or create an account if you have not already.
  • Click Create an App.
  • Fill out the Name and Description and click Create.
  • Copy down the Client ID.
  • Click Show Client Secret and copy it down.
  • Click Edit Settings. and add http://localhost:3000 as the redirect URI.
Instagram Stats

After completing all these steps, you will have properly configured your Spotify application and we can move to authentication.

Authentication

Although there are many ways to authenticate with the Spotify API, we will be using the Authorization Code Flow since we only need the permission granted once.

We need to have our new Spotify application request authorization by logging in with our Spotify account with whatever scopes we need.

  • For more information about Spotify API scopes, you can visit their documentation on scopes.

Below is an example of what the authorization request URL would look like. You would replace the CLIENT_ID with your Client ID and the SCOPE with the ones you want to access. For my purposes, I only needed to use the one scope user-read-currently-playing.

https://accounts.spotify.com/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=http
%3A%2F%2Flocalhost:3000&scope=SCOPE1%20SCOPE2

After visiting this URL and authorizing, you will be redirected to your redirect URI and there will be a CODE appended to the URL. Copy down the CODE because we will need this to retrieve the Refresh Token.

http://localhost:3000/callback?code=CODE

Before we retrieve the Refresh Token we need to generate a Base 64 encoded string that contains our Client ID and Client Secret in the format of CLIENT_ID:CLIENT_SECRET. We can easily do this by using base64encode.org.

Afterwards, we can retrieve the Refresh Token using the curl command with our Base 64 encoded CLIENT_ID:CLIENT_SECRET and CODE below in our terminal.

curl -H "Authorization: Basic <ENCODED-CLIENT_ID:CLIENT_SECRET>"
-d grant_type=authorization_code -d code=CODE -d redirect_uri=http%3A
%2F%2Flocalhost:3000 https://accounts.spotify.com/api/token

The command will return a response that contains the Refresh Token. Copy the Refresh Token as we need this to use the Spotify API.

Environment Variables

Next.js has built-in support for loading environment variables from .env.local, so we will create a .env.local file in our project's root directory and declare our variables. Below is an example of what the .env.local file would look like.

Replace the CLIENT_ID, CLIENT_SECRET, and REFRESH_TOKEN with your values.

.env.local
SPOTIFY_CLIENT_ID=CLIENT_ID
SPOTIFY_CLIENT_SECRET=CLIENT_SECRET
SPOTIFY_REFRESH_TOKEN=REFRESH_TOKEN
  • For more information about Next.js environment variables, you can visit their documentation on Environment Variables.

Next.js API Routes

By using our three environment variables, we can request an Access Token to securely request data from the Spotify API.

The code below is to request the song we are currently listening to; however, you can modify the code for the other scopes that we have access to from the Spotify API.

pages/api/spotify.js
import querystring from 'querystring';

const {
  SPOTIFY_CLIENT_ID: client_id,
  SPOTIFY_CLIENT_SECRET: client_secret,
  SPOTIFY_REFRESH_TOKEN: refresh_token,
} = process.env;

const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64');
const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`;
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;

const getAccessToken = async () => {
  const response = await fetch(TOKEN_ENDPOINT, {
    method: 'POST',
    headers: {
      Authorization: `Basic ${basic}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: querystring.stringify({
      grant_type: 'refresh_token',
      refresh_token,
    }),
  });

  return response.json();
};

export const getNowPlaying = async () => {
  const { access_token } = await getAccessToken();

  return fetch(NOW_PLAYING_ENDPOINT, {
    headers: {
      Authorization: `Bearer ${access_token}`,
    },
  });
};

export default async (_, res) => {
  const response = await getNowPlaying();

  if (response.status === 204 || response.status > 400) {
    return res.status(200).json({ isPlaying: false });
  }

  const song = await response.json();
  const isPlaying = song.is_playing;
  const title = song.item.name;
  const artist = song.item.artists.map((_artist) => _artist.name).join(', ');
  const album = song.item.album.name;
  const albumImageUrl = song.item.album.images[0].url;
  const songUrl = song.item.external_urls.spotify;

  return res.status(200).json({
    album,
    albumImageUrl,
    artist,
    isPlaying,
    songUrl,
    title,
  });
};

API Response

If everything has been setup correctly, you should see a response similar to the one below by visiting localhost:3000/api/spotify after running yarn dev or npm dev. This route will return with information about the song we are currently listening to without the excess.

{
  "album": "Libyus Music Sound History 2004-2010",
  "albumImageUrl": "https://i.scdn.co/image/ab67616d0000b27353676a887a983e98261f0c9d",
  "artist": "DJ Okawari",
  "isPlaying": true,
  "songUrl": "https://open.spotify.com/track/2LDCP8QWhIB42gRvSVgRxO",
  "title": "Flower Dance"
}

The component in my footer is just an example of what you can do with this response data.