Introduction
On my personal 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.
1. Create an Application on Spotify Developer
- Go to Spotify Developer Website.
- Click Create An App
- Fill in App Name, App description, then Create
- Next, you will be provided with
Client ID
andClient Secret
(Don't give this secret to anyone)
- Open edit settings, then fill out
http://localhost:3000
on RedirectURIs
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
example:
https://accounts.spotify.com/authorize?client_id=eaccb97f6d0e405897adf1dd80b95c01&response_type=code&redirect_uri=http
%3A%2F%2Flocalhost:3000&scope=user-read-currently-playing
Open that link in a browser, then you will get redirected into a uri, copy the website link
Example of the redirect link:
http://localhost:3000/?code=AQBeA9SD7QbA9hUfv_TfmatYxT51CY87msMnOZmMbhf7ZaxfbvG7oKEsATOJBxDyFap0Aq6uftY0v4Hq1QSy3MgQBfAHhmrifty-62rfDRlFnd0AzXRBOMpoOSA6SNw_uTPp7AixAE5zosgiIIf7efhzf1QOJfLh1HUYi248z8jk1x2jjKG2YLvMyJuP0rjB5tP5UHjoFGBvKbULpchkF6yiJHnS
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:
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
*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
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"
}
Example on the 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
or, if you prefer typescript, there is also a starter template
After all app is installed, add querystring dependency
yarn add querystring
or
npm i querystring
Next, make an api route in /pages/api/spotify.js
// /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,
});
};
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
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
Add SWR in pages/index.jsx like this:
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>
</>
);
}
There will be 2 types of JSON data that will be sent by the Spotify API:
- When there is no song playing
{
"isPlaying": false
}
- 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"
}
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 items-center p-5 space-x-4 transition-shadow border rounded-md hover:shadow-md w-72'
>
<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='font-bold component'>
{data?.isPlaying ? data.title : 'Not Listening'}
</p>
<p className='text-xs font-dark'>
{data?.isPlaying ? data.artist : 'Spotify'}
</p>
</div>
<div className='absolute bottom-1.5 right-1.5'>
<SiSpotify size={20} color={'#1ED760'} />
</div>
</a>
You can check out the live deployment on spotify-playing.theodorusclarence.com
Originally posted on my personal site, find more blog posts and code snippets library I put up for easy access on my site 🚀
Top comments (5)
I deployed the project on vercel but the api is not working there what changes i have to do so that i can make it work. Can you please tell. I have added the redirect route also as my website address.
dont forget to add the api key to the deployment env
When i do the curl command i get
{"error":"invalid_client"}%
How to fix???
Awesome tutorial, thank you! I decided to modify mine to show most recently played as I prefer being able to always show a song (for anyone interested just change the scope at step 2 to user-read-recently-played and modify the api endpoint in spotify.js, also make sure you handle the response.json() correctly too)
Yeah, it works on dev but not production for me either.