HomeBlogsSnippetsAbout Me

How to integrate Spotify API to list Top Tracks and Currently Playing music in Next JS (14.0.1) App router

Bimal Thapa Magar

Bimal Thapa Magar

1 year ago

7 min read

Back

Want to show your top ten Spotify tracks and now playing songs on your portfolio website built with the latest Next.js App router (v14.0.1)? This is the gudie for you that will walk you through the process, starting from scratch, to showcase both your currently playing song and the top 10 tracks you've been listening to on Spotify

You need to follow these step by step guide in order to integrate Spotify's API.


1. CREATE AN APPLICATION


Firstly, you need to authenticate yourself in order to get access for fetching the Spotify's API.And, for that you need to create an spotify application. Here are the steps:


  • Go to your Spotify developer dashboard and log in to your account.
  • Then, click on Create app button just below the navbar on top right corner of your dashboard.
  • Next, fill all the fields, App name, App description,Website and on Redirect URIs field, type http://localhost:3000 as your redirect URI.
  • Then click on Save.You will be redirected to your newly created app now.
  • Next, click on Settings on top right corner, just below the navbar.There you will get your client_id and just below that you will see View client secret button.
  • Now, click on that button and save both client_id and client_secret.Both will be needed later.

Congratulations!, now you have all credentials in order to authenticate the Spotify's APIs.


2. AUTHORIZATION


Now, it's time to authenticate the Spotify API using the previously saved credentials. Spotify offers various Authorization methods, and for now, we'll be utilizing the Authorization Code Flow.


Initially, our application needs to be authorized with specific scopes. Scopes serve the purpose of granting confidence to share only the selected information and nothing beyond that. For instance, in my application, I only intend to retrieve the top ten tracks and the currently playing song from Spotify's Developer API. To achieve this, I must select the scopes user-top-read and user-read-currently-playing from the scopes list respectively. Here's an example of the URL for authorization with these scopes.


https://accounts.spotify.com/authorize?client_id=<client_id_you_saved_before>&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000&scope=user-read-currently-playing%20user-top-read

Now, copy the provided URL and paste it into your browser's address bar. Ensure that your localhost:3000 is running. is actively running. After pressing enter, you'll be redirected to http://localhost:3000?code= , where you will receive a code as a query parameter. Here's an example of the URL you can expect at this stage.

http://localhost:3000/?code=AQB3x..............................

Now, save this code.You will need it later for retrieving your refresh_token.


Next, you will need to generate the refresh_token in order to revoke the access_token--which expires frequently.For that open up your terminal and then type the following code.


curl -d client_id=<your_client_id> -d client_secret=<your_client_secret> -d grant_type=authorization_code -d code=<code_that_you_saved_from_redirected_uri> -d redirect_uri=http://localhost:3000 https://accounts.spotify.com/api/token

You now will get the JSON response in the following format.


{
    "access_token":"your_access_token_here",
    "token_type":"Bearer",
    "expires_in":3600,
    "refresh_token":"your_refresh_token_here",
    "scope":"user-read-currently-playing"
}

After that save the refresh_token from the response and save it for later.You will need to use this in Next.js application. This refresh_token is valid indefinitely until and unless the user it represents revokes access.


3.Using Spotify's API in Next.js(14.0.1) App router


Firstly, you have to set up the environment variables in .env file outside the app directory in your next js application.Add the environment variables as below.Replace these values with your own values you saved before like before.

SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
SPOTIFY_REFRESH_TOKEN=

Secondly, let's create a lib/spotify.js , to look more organized folder structure, where we will be writing the API fetching logic. Your code should look like this.


lib/spotify.js
import queryString from 'query-string';

const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
const refresh_token = process.env.SPOTIFY_REFRESH_TOKEN;
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 TOP_TRACKS_ENDPOINT = `https://api.spotify.com/v1/me/top/tracks`;

//After the access_token expires, getting new access_token with refresh_token we obtained before
const getAccessToken = async () => {
	try {
		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
			})
		});;
		const responseData = await response.json();
		return responseData;
	} catch(err){
		throw new Error(JSON.stringify(err))
	}

};

//Get currently playing song
export const getNowPlaying = async () => {
	try {
		const {access_token} = await getAccessToken();

		return fetch(NOW_PLAYING_ENDPOINT,{
	  		headers:{
	  			Authorization:`Bearer ${access_token}`
	  		}
  		});
	} catch(err){
		throw new Error(JSON.stringify(err))
	}
};

//Get top tracks played on your Spotify account
export const getTopTracks = async () => {
	try {
		const {access_token} = await getAccessToken();
		
		return fetch(TOP_TRACKS_ENDPOINT,{
			headers:{
				Authorization:`Bearer ${access_token}`
			}
		});
	} catch(err){
		throw new Error(JSON.stringify(err))
	}
};


4.Creating an API route


Cheers 🥂!, Everything is setup. Now at last we need to setup two api routes in order to send the requests and get response from the spotify's API. For that you have to create two files app/api/now-playing/route.js and app/api/top-tracks/route.js in your application.The equivalent code for those two endpoints looks like this.


app/api/now-playing/route.js
import { NextResponse } from 'next/server'
import {getNowPlaying} from "../../../lib/spotify";

export const dynamic = 'force-dynamic';
//--------------OR---------------------//
export const revalidate = 0;

export async function GET(request) {
    const response = await getNowPlaying();
    if(response?.status === 204 || response?.status > 400) {
        return NextResponse.json({isPlaying:false},{status:200});
    }
    
    try {
        const song = await response.json();
        console.log('song',song?.item?.name);
        const isPlaying = song?.is_playing;
        const name = 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?.album.external_urls.spotify;
    
        return NextResponse.json({
            isPlaying,
            album,
            albumImageUrl,
            name,
            songUrl,
            artist
        },{
            status:200
        });
    } catch(err) {
        return NextResponse.json({
            isPlaying:false
        },{
            status:200
        });
    }
}

app/api/top-tracks/route.js
import { NextResponse } from 'next/server'
import {getTopTracks} from "../../../lib/spotify";

export const dynamic = 'force-dynamic';
//--------------OR----------------------//
export const revalidate = 0;
export async function GET(request) {
    const response = await getTopTracks();

    if(response.status === 204 || response.status > 400) {
        return NextResponse.json({tracks:[]},{status:200});
    }
    try {
        const {items} = await response.json();
        const tracks = items.slice(0,10).map(track => {
            return {
                artist:track.artists.map(artist => artist.name).join(", "),
                songUrl:track.external_urls.spotify,
                title:track.name,
                imageUrl:track.album.images.map(image => image.url)[1]
            };
        });
        return NextResponse.json({tracks},{
            status:200
        });
     } catch(err){
        return NextResponse.json({tracks},{status:200});
     }
}

Note: In the provided code, you'll notice two lines as shown below 👇. You can choose either of them; both are optional, and you can select the one you prefer. This flexibility exists because, by default, the Next.js App router caches routes. This means that if the same endpoint is accessed from the client side, the router utilizes the cached response. If you don't use these options, your "now-playing" endpoint may not update, resulting in the same cached response being displayed and causing a failure to show the currently playing music in the UI.Additinally, feel free to modify the JSON response from those endpoints as per your need or demand.

export const dynamic = 'force-dynamic';
//-----------OR----------------------//
export const revalidate = 0;

5.Conclusion


Everything is complete! Now it's time to retrieve data from the two endpoints you've established. This is the way to showcase your top ten tracks and currently playing songs on your Next.js website, allowing users to see what you're listening to.

POV: You have the option to utilize swr, react query or official fetch api or client-side data fetching in React.js. For simplicity, I'll be using swr. Here's a code snippet demonstrating how to implement SWR for this particular use case.


YourClientComponent.js
import useSWR from 'swr';
const YourClientComponent = () => {
    //Fetch data in a periodical interval of 1 seconds
    const {data,error} = useSWR('/api/now-playing',fetcher,{refreshInterval:1000});

    return (
        <div>
          {
            error && <p> Oops! Error dude 👀 </p>
          }
          {
            data?.isPlaying ? (<h1>{data?.name}</h1>):<p>Not Playing</p>
          }
        </div>
    )
};

export default YourClientComponent;


Consequently, you can integrate Spotify's API like as such in Next.js APP Router.Follow me on 👉 GitHub.


Keep coding, Keep learning and Keep listening music 🎸.😜😜


Spotify Icon-

Not Playing

HomeAbout MeBlogGithubWorksLinked In

Home

Blogs

Snippets

About Me