Skip to main content
Photo from unsplash: spotify-now-playing_n37szf

How to show Now Playing in Spotify with Next.js

Written on January 25, 2021 by Theodorus Clarence.

Last updated November 12, 2021.

See changes
5 min read
––– views
Read in Bahasa Indonesia

Introduction

On this website, I use Spotify API to show what song is currently playing. Now, I will try to explain on how do I do that.

Next.js has a built-in API in a single application, so choosing Next.js is a perfect choice so we don't expose our API keys.

spotify-playing

Website Demo


1. Create an Application on Spotify Developer

  • Go to Spotify Developer Website.
  • Click Create An App
  • Fill in App Name, App description, then Create
Dashboard
  • Next, you will be provided with Client ID and Client Secret (Don't give this secret to anyone)
Client Info
  • Open edit settings, then fill out http://localhost:3000 on RedirectURIs
Edit Settings

The first step is done! Now, you need to do authentication to get access & refresh token


2. Authenticate Your Account

To do authentication, we need to prepare CLIENT_ID and put it into this link below:

https://accounts.spotify.com/authorize?client_id=CLIENT_ID_HERE&response_type=code&redirect_uri=http %3A%2F%2Flocalhost:3000&scope=user-read-currently-playing
text

example:

https://accounts.spotify.com/authorize?client_id=eaccb97f6d0e405897adf1dd80b95c01&response_type=code&redirect_uri=http %3A%2F%2Flocalhost:3000&scope=user-read-currently-playing
text

Open that link in a browser, then you will get redirected into a uri, copy the website link

Redirect URI

Example of the redirect link:

http://localhost:3000/?code=AQBeA9SD7QbA9hUfv_TfmatYxT51CY87msMnOZmMbhf7ZaxfbvG7oKEsATOJBxDyFap0Aq6uftY0v4Hq1QSy3MgQBfAHhmrifty-62rfDRlFnd0AzXRBOMpoOSA6SNw_uTPp7AixAE5zosgiIIf7efhzf1QOJfLh1HUYi248z8jk1x2jjKG2YLvMyJuP0rjB5tP5UHjoFGBvKbULpchkF6yiJHnS
text

code that you have is the one after (=). Don't forget to write it down.

Next we need to get authorization client that is already encrypted with base64, use this website to encrypt with the format of client_id:client_secret

For example:

Base64 Encode

Next, write down the encrypted base64

After that, open up terminal/cmd, and run this command, don't forget to change the base64 and the code to yours.

curl -H "Authorization: Basic CHANGE_BASE64_HERE" -d grant_type=authorization_code -d code=CHANGE_CODE_HERE -d redirect_uri=http%3A %2F%2Flocalhost:3000 https://accounts.spotify.com/api/token
bash

*make sure the command is in one line

Example:

curl -H "Authorization: Basic ZWFjY2I5N2Y2ZDBlNDA1ODk3YWRmMWRkODBiOTVjMDE6YTQxOTVjMmQwYTQyNDM2MDllNjk3ZTYwMmU3MGI3NjI=" -d grant_type=authorization_code -d code=AQBeA9SD7QbA9hUfv_TfmatYxT51CY87msMnOZmMbhf7ZaxfbvG7oKEsATOJBxDyFap0Aq6uftY0v4Hq1QSy3MgQBfAHhmrifty-62rfDRlFnd0AzXRBOMpoOSA6SNw_uTPp7AixAE5zosgiIIf7efhzf1QOJfLh1HUYi248z8jk1x2jjKG2YLvMyJuP0rjB5tP5UHjoFGBvKbULpchkF6yiJHnS -d redirect_uri=http%3A%2F%2Flocalhost:3000 https://accounts.spotify.com/api/token
bash

You will get a JSON like this:

{ "access_token": "BQDKxO7h1I1wA3esGK9zCFWn97XORJEPjwAHAEIxCnDXcmy9GbEuPacquwWvpiM4d33gJVHVOP9KUxY8AXkpXc-_zRFZBfneHM2vEeV1Fbfr-0Mw94oimlNf77dRiyxPpm4IUVNLloUWgYcfkAO0", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "AQAtxXvnzRTt4c2-2_Av2WyJQKWxUW_hMVN6QNiqv2i8A2ZElVarmvdhqyc8Pf-Z5n827FTFxTpHq5E3kOsrlRWM3TuJWxjVQsW0icR0zo3BXRFLt2FB2Qfj-pFaZwY-qc8", "scope": "user-read-currently-playing" }
json

Example on the terminal:

Terminal

what we need to write down is the refresh_token. That token will last infinitely

Now you can do the request with Next.js or another backend application


3. Creating API routes in Next.js

If you need a reference to create the app, you can check my repository. Don't forget to star it!

You can also use my nextjs-tailwind-starter by using:

npx create-next-app -e https://github.com/theodorusclarence/nextjs-tailwind-starter project-name
bash

After all app is installed, add querystring dependency

yarn add querystring or npm i querystring
bash

Next, make an api route in /pages/api/spotify.js

If you want the TypeScript version, checkout the code on GitHub

// /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 || response.data.currently_playing_type !== 'track' ) { return res.status(200).json({ isPlaying: false }); } const data = { isPlaying: response.data.is_playing, title: response.data.item.name, album: response.data.item.album.name, artist: response.data.item.album.artists .map((artist) => artist.name) .join(', '), albumImageUrl: response.data.item.album.images[0].url, songUrl: response.data.item.external_urls.spotify, }; res.status(200).json(data); };
jsx

Add .env.local with authorization data that we have written (change the data below with yours)

SPOTIFY_CLIENT_ID=eaccb97f6d0e405897adf1dd80b95c01 SPOTIFY_CLIENT_SECRET=a4195c2d0a4243609e697e602e70b7 SPOTIFY_REFRESH_TOKEN=AQAtxXvnzRTt4c2-2_Av2WyJQKWxUW_hMVN6QNiqv2i8A2ZElVarmvdhqyc8Pf-Z5n827FTFxTpHq5E3kOsrlRWM3TuJWxjVQsW0icR0zo3BXRFLt2FB2Qfj-pFaZwY-qc8
text

Your API is ready with route: GET https://localhost:3000/api/spotify


4. Use API with Next.js

For data fetching, we can use SWR. SWR is a great library that can fetch the API periodically. SWR will do refetching each time we refocus a the window. Also, install react-icons to get the spotify logo.

yarn add swr react-icons or npm i swr react-icons
bash

Add SWR in pages/index.jsx like this:

TypeScript Version

import useSWR from 'swr'; export default function Home() { const fetcher = (url) => fetch(url).then((r) => r.json()); const { data } = useSWR('/api/spotify', fetcher); return ( <> <section className='bg-gray-600'> <main className='flex items-center justify-center'> {console.log(data)} </main> </section> </> ); }
jsx

There will be 2 types of JSON data that will be sent by the Spotify API:

  1. When there is no song playing

    { "isPlaying": false }
    json
  2. When there is a song playing

    { "album": "Menari Dengan Bayangan", "albumImageUrl": "https://i.scdn.co/image/ab67616d0000b273d623688488865906052ef96b", "artist": "Hindia", "isPlaying": true, "songUrl": "https://open.spotify.com/track/08OPqLv99g8avzmxQepmiw", "title": "Besok Mungkin Kita Sampai" }
    json

So, we can conditionally render the data like this:

<a target='_blank' rel='noopener noreferer' href={ data?.isPlaying ? data.songUrl : 'https://open.spotify.com/user/erence21?si=yTsrZT5JSHOp7tn3ist7Ig' } className='relative flex w-72 items-center space-x-4 rounded-md border p-5 transition-shadow hover:shadow-md' > <div className='w-16'> {data?.isPlaying ? ( <img className='w-16 shadow-sm' src={data?.albumImageUrl} alt={data?.album} /> ) : ( <SiSpotify size={64} color={'#1ED760'} /> )} </div> <div className='flex-1'> <p className='component font-bold'> {data?.isPlaying ? data.title : 'Not Listening'} </p> <p className='font-dark text-xs'> {data?.isPlaying ? data.artist : 'Spotify'} </p> </div> <div className='absolute right-1.5 bottom-1.5'> <SiSpotify size={20} color={'#1ED760'} /> </div> </a>
jsx

You can check out the live deployment on spotify-playing.theodorusclarence.com

Thanks and Goodluck!

Tweet this article

Enjoying this post?

Don't miss out 😉. Get an email whenever I post, no spam.

Subscribe Now