Build a Spotify Player with Claude Code
Use Claude Code to build a Spotify web app with OAuth and in-browser playback.
Introduction
30 Second Summary
Every music streaming app gives you algorithmic recommendations, but sometimes the best way to discover something new is pure randomness. What if you had a personal jukebox that served you one surprise album every single day?
In this project, you will use Claude Code to build a web app that logs you into Spotify, picks a random album based on today's date, and lets you play it right in your browser.
What You'll Build
Imagine opening a page each morning, seeing an album you have never heard of with its cover art front and center, and pressing play to stream it directly from your browser tab.
By the end of this project, you'll have:
- A working Spotify login that authenticates you securely using the OAuth 2.0 PKCE flow, displaying today's random album with its cover art, title, artist, and release year.
- A play button that streams music directly in your browser by turning it into a Spotify Connect device using the Web Playback SDK.
- A custom-designed UI that you created by writing design prompts to Claude Code, making the app look and feel like your own creation.
- Secret Mission: Add track-by-track navigation so you can skip through the album and jump to any song.
Are there any prerequisites?
You need a Spotify Premium account (required for the Web Playback SDK) and a Claude Pro, Max, Team, or Enterprise subscription (required for Claude Code access). You also need a Mac with Terminal available.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters to you.
Set Up Claude Code and Spotify Credentials
To build your Album of the Day app, you need two things talking to each other: an AI coding assistant that generates code from your descriptions, and API credentials that let that code access Spotify's music library and playback features.
This step confirms your tools are ready. You will verify Claude Code is installed, confirm your Spotify Developer app credentials are in place, and make sure Python 3 is available to run a local server later.
In this step, get ready to:
- Verify Claude Code is installed and authenticated.
- Confirm your Spotify Developer app credentials are ready.
- Verify Python 3 and navigate into your project folder.
Verify Claude Code is installed
Claude Code is a terminal-based AI assistant that generates entire applications from natural language prompts. Before you start prompting it, confirm it is ready to go.
- Confirm Claude Code is installed by running this command in your Terminal:
claude --version
You should see a version number printed, something like 2.1.220 (your exact number may differ).
What is Claude Code?
Claude Code is Anthropic's AI coding tool that runs directly in your terminal. You describe what you want in plain English, and it writes the code for you. It can create files, edit existing code, and run commands.
It requires a Claude Pro, Max, Team, or Enterprise subscription.
Command not found?
If your terminal says claude: command not found, reinstall Claude Code by running:
curl -fsSL https://claude.ai/install.sh | bash
Close and reopen your Terminal after the install completes, then try claude --version again.
Need more help?
Confirm your Spotify Developer app credentials
Your Spotify Developer app is what grants your code permission to search albums and control playback. You need to confirm the Client ID is accessible and the Redirect URI is correct.
- Return to the Spotify Developer Dashboard at https://developer.spotify.com/dashboard.
- Click on your app name to open its settings.
- Confirm your Client ID is visible near the top of the page. Copy it somewhere safe (a text file or notes app) if you have not already.
- Click Settings and scroll down to Redirect URIs. Confirm you see http://127.0.0.1:8000 listed.
Why 127.0.0.1 instead of localhost?
Spotify requires HTTPS for redirect URIs, with one exception: loopback IP addresses. The IP literal 127.0.0.1 is allowed without HTTPS, but the hostname localhost is not. Always use the IP form for local development with Spotify.
Don't see your Client ID?
Make sure you selected both Web API and Web Playback SDK when creating the app. If either is missing, click Settings and update the selected APIs.
Help me find my Spotify Client ID
Verify Python 3 and navigate into your project folder
You will use Python 3 later to run a simple local web server that serves your app files. Confirm it is available on your machine.
- Check your Python 3 version by running this command:
python3 --version
You should see output like Python 3.x.x (any version of Python 3 works for this project).
Seeing a popup about Command Line Tools?
On macOS, running python3 for the first time may trigger a prompt to install Command Line Tools. Click Install and wait for it to finish. Then run python3 --version again.
Python 3 is not working on my Mac
- Navigate into your project folder by running:
cd ~/Desktop/[[PROJECT_FOLDER="album-of-the-day"]]
- Confirm you are inside the folder by running:
pwd
You should see a path ending with your project folder name, like /Users/yourname/Desktop/album-of-the-day.
Before you move on, predict: what do you think you will see if you run ls inside this folder right now?
- Check the folder contents by running:
ls
The folder is empty. That is exactly right. Claude Code will generate all the files for you in the next step.
Your tools are locked and loaded. You have Claude Code ready to generate code, a Spotify Developer app with credentials to access the music library, and Python 3 standing by to serve your files. Next up, you will give Claude Code your first prompt and watch it build the entire authentication flow and album display in one shot.
Prompt Claude Code to Build the Core App
Your environment is ready and your Spotify Developer app has a Client ID waiting to be used. Now it's time to build the actual application that authenticates with Spotify and displays album data.
Instead of writing hundreds of lines of JavaScript by hand, you'll describe what you want to Claude Code in plain English. It will generate the entire OAuth 2.0 authentication flow, the album search logic, and the display UI for you.
In this step, get ready to:
- Give Claude Code a detailed prompt describing your app.
- Start a local server to run the generated files.
- Log in with Spotify and confirm today's album appears.
Start Claude Code and give it your prompt
Claude Code works as an interactive session in your terminal. You type natural language descriptions of what you want, and it generates the code for you.
- Start a Claude Code session by running this command in your terminal:
claude
What happens when you run this?
Claude Code opens an interactive prompt inside your terminal. You'll see a text input area where you can type or paste natural language instructions. Everything you type here gets sent to Claude, which can then create files, run commands, and build your project.
Now you'll give Claude Code a detailed prompt describing the app you want to build. The more specific you are, the better the result.
- Type or paste the following prompt into your Claude Code session, replacing the Client ID placeholder with your actual Client ID from the Spotify Developer Dashboard:
Build a single-page web app with three files: index.html, style.css, and app.js.
The app should:
- Implement Spotify OAuth using the PKCE flow (no backend server needed)
- Use Client ID: [[SPOTIFY_CLIENT_ID="your Client ID from the Spotify Dashboard"]] and redirect URI: http://127.0.0.1:8000
- Request these scopes: streaming user-read-email user-read-private user-modify-playback-state
- After login, search for a random album using today's date as a seed (hash the date string to pick a search term and offset from a list of genre keywords)
- Display the album's cover art, name, artist, and release year
- Include a Play button (we will add the playback logic later)
- Use a dark theme with Spotify-green (#1db954) accent colors
- Load the Spotify Web Playback SDK script from https://sdk.scdn.co/spotify-player.js in index.html (we will use it in a later step)
What does this prompt do?
This single prompt gives Claude Code everything it needs to generate a complete working app. The PKCE flow handles authentication securely in the browser without a backend server.
The date-based seed means the app picks a different album each day, but everyone sees the same album on the same day. Including the scopes and SDK script now saves you from re-authenticating later when you add playback.
Claude Code will ask for permission
When Claude Code is ready to create files, it will show you what it wants to write and ask for your approval. Review what it shows you, then approve each file creation. You can press Enter or type y to approve.
After Claude Code finishes generating, it will have created three files in your project folder.
- Verify the files were created by running this command in a separate terminal tab (press Cmd+T to open a new tab):
ls
You should see index.html, style.css, and app.js listed in the output.
Don't see all three files?
If Claude Code only created one or two files, switch back to your Claude Code session and ask it to create the missing files. For example: "You missed style.css, please create it too."
If you see no files at all, make sure your new terminal tab is in the same project folder. Run pwd to check your current directory.
Need more help? Help me troubleshoot my Claude Code file generation
Start the local server
Your app files need a web server to handle the OAuth redirect. Python's built-in server is perfect for this.
- In your new terminal tab (not the Claude Code session), make sure you are in your project folder, then start the server by running:
python3 -m http.server 8000
You should see output like Serving HTTP on :: port 8000 confirming the server is running.
Why a local server?
Opening the HTML file directly (with a file:// URL) would break the OAuth redirect. Spotify requires the redirect URI to match exactly what you registered: http://127.0.0.1:8000. The Python server provides that address.
Port already in use?
If you see an error about the port being in use, another process is already on port 8000. Stop any other servers you might have running, or use a different port and update your Spotify app's redirect URI to match.
Help me fix my local server
Test the login flow
Your app is now being served locally. Time to test the full authentication flow and confirm today's album appears.
- Open Chrome and navigate to:
- http://127.0.0.1:8000
You should see a dark-themed page with the title "Album of the Day" and a green "Log in with Spotify" button.
- Click Log in with Spotify.
- Spotify's authorization page will appear asking you to grant access to your app.
- Click Agree to authorize.
Before you look at the result, what do you expect to see after authorizing?
After you authorize, the page redirects back to your app. You should now see today's album displayed with its cover art, title, artist name, and release year.
✔️ I see an album displayed
Your app is working. The PKCE authentication flow completed successfully, and your app searched Spotify for today's random album. The album you see will change tomorrow.
ⓧ I see an error or blank page
Open the browser's developer console to see what went wrong.
- Press Cmd+Option+J (macOS) or Ctrl+Shift+J (Windows) to open the Console.
- Look for red error messages.
- Switch back to your Claude Code session and describe the error to it. For example: "I'm getting this error in the browser console: [paste the error]."
- After Claude Code fixes the code, refresh the page and try logging in again.
Common fixes
If the error mentions your Client ID, double-check that Claude Code used your actual ID in app.js, not a placeholder. If the redirect fails, confirm your Spotify app's redirect URI is exactly http://127.0.0.1:8000 with no trailing slash.
Your app is authenticating with Spotify and showing you a new album every day. Next up, you'll add a play button so you can actually listen to the album right in the browser.
Add a Play Button
You can see today's album with its cover art and details. The obvious next thing you want to do is hear it.
In this step, you'll prompt Claude Code to add a play button that calls the Spotify Web API's playback endpoint. You'll discover an important limitation that every Spotify developer encounters on their first try.
In this step, get ready to:
- Prompt Claude Code to wire up the play button with Spotify's playback API.
- Test the play button and observe the result.
- Identify why the browser can't play music by default.
Prompt Claude Code to add playback
The play button is already visible in your UI from Step 2, but clicking it does nothing yet. You need a function that tells Spotify's API to start playing the album.
- Switch back to your Claude Code session in Terminal.
- Give Claude Code a prompt describing what you want. Here is an example:
Add a togglePlay function to app.js that handles the play button. When clicked, it should:
- Check if deviceId exists. If not, show "Player not ready yet..." in the status-message element and return early.
- If isPlaying is true, call player.pause()
- Otherwise, call PUT https://api.spotify.com/v1/me/player/play with the device_id as a query parameter, and send context_uri (the album URI), offset position 0, and position_ms 0 in the body.
- If the response is not ok, parse the error JSON and show the error message in status-message.
- Also add an event listener that connects the play-btn click to this togglePlay function.
Make sure user-modify-playback-state is in the SCOPES string.
Why describe the logic in detail?
The more specific your prompt, the closer Claude Code's output matches what you need. Naming exact element IDs, API endpoints, and variable names means fewer rounds of back-and-forth fixing.
Claude Code generates the function and wires it to the button. Verify the key function it created looks like this:
async function togglePlay() {
if (!deviceId) {
document.getElementById('status-message').textContent = 'Player not ready yet...';
return;
}
if (isPlaying) {
await player.pause();
} else {
const response = await fetch(
`https://api.spotify.com/v1/me/player/play?device_id=${deviceId}`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
context_uri: currentAlbumUri,
offset: { position: 0 },
position_ms: 0,
}),
}
);
if (!response.ok) {
const error = await response.json();
console.error('Playback error:', error);
document.getElementById('status-message').textContent = 'Playback error: ' + (error.error?.message || 'Unknown');
}
}
}
What does this code do?
The function first checks if deviceId exists. If it's null, the function shows a message and stops. This guard matters because you can't send a play command without a target device.
When deviceId is set, the function calls Spotify's Start Playback endpoint (PUT /me/player/play) with the album's context_uri. This tells Spotify which album to play and on which device.
- Also confirm Claude Code added the event listener. Look for this line near the bottom of app.js:
document.getElementById('play-btn').addEventListener('click', togglePlay);
- Verify the SCOPES constant includes user-modify-playback-state. It should already be there from Step 2.
What is user-modify-playback-state?
Spotify uses scopes to control what your app can do with a user's account. The user-modify-playback-state scope gives your app permission to start, pause, and skip playback. Without it, the play endpoint returns a 403 error.
Claude Code generated something different?
If the function Claude Code generated doesn't match, describe the differences in your next prompt. For example: "The togglePlay function should check deviceId first and return early if it's null, showing 'Player not ready yet...' in the status-message element."
help me fix my togglePlay function to match the expected behavior
Test the play button
The code is in place. Time to see what happens when you click play.
- Switch to Chrome and refresh http://127.0.0.1:8000 to load the updated app.js.
- Log in with Spotify again (click the login button and authorize the app).
- Confirm you see today's album displayed with the green Play button below it.
Before you click the play button, take a moment to predict: what do you think will happen? Will you hear music in the browser?
- Click the Play button.
- Look at the status text below the button.
You see "Player not ready yet..." appear in the status area. No music plays.
This is expected. The play button does not work yet.
The togglePlay function checks if deviceId exists before calling the API. Right now, deviceId is null. The function bails out immediately and shows the status message instead of making the API call.
Open your browser console (Cmd+Option+J on macOS or Ctrl+Shift+J on Windows) to confirm there are no JavaScript errors. The code is working correctly. It just has nowhere to send the music.
Understand the problem
The play button tried to send a play command, but there is no device to receive it. This is the most common surprise for developers building with the Spotify Web API for the first time.
Why is deviceId null?
The Spotify Web API's playback endpoints (PUT /me/player/play) send commands to Spotify Connect devices. Your phone's Spotify app, your desktop Spotify app, and smart speakers are all Spotify Connect devices. Your browser is not one by default.
To make the browser a playback device, you need to register it using the Spotify Web Playback SDK. The SDK creates a virtual Spotify player inside your browser tab, gives it a device ID, and makes it appear in the "Devices Available" list alongside your phone and desktop app.
Without the SDK, your only options are: send play commands to a different device (like your phone), or accept the error. Neither is what you want for an in-browser music player.
Your play button is wired up and ready. The missing piece is turning your browser into a Spotify Connect device. That is exactly what the Web Playback SDK does, and you will add it in the next step.
Fix Playback with the Web Playback SDK
In the last step, you hit the wall every Spotify developer encounters: clicking play either sent music to your phone or returned a "No active device found" error.
The Web Playback SDK solves this by registering your browser as a Spotify Connect device. In this step, you will prompt Claude Code to initialize the SDK so the play button streams music directly in Chrome.
In this step, get ready to:
- Prompt Claude Code to initialize the Web Playback SDK player.
- Re-authenticate with Spotify and test in-browser playback.
- Verify the play/pause toggle works correctly.
Prompt Claude Code to integrate the Web Playback SDK
The SDK script tag is already in your index.html from the previous step. Now you need the JavaScript that actually creates a player instance and connects it.
- Switch back to your Claude Code session in Terminal.
- Give Claude Code this prompt to integrate the Web Playback SDK:
Add the Spotify Web Playback SDK initialization to app.js. Create an initializePlayer() function that:
- Creates a new Spotify.Player instance named 'Album of the Day' with volume 0.5
- Uses a getOAuthToken callback that passes the accessToken
- Listens for the 'ready' event to capture the device_id into the deviceId variable, and logs 'Ready with Device ID' plus the ID to console
- Listens for 'not_ready', 'initialization_error', 'authentication_error', and 'account_error' events with appropriate error messages shown in the status-message element
- Listens for 'player_state_changed' to update isPlaying and toggle the play button text between 'Play' and 'Pause'
- Calls player.connect() at the end
Also add a window.onSpotifyWebPlaybackSDKReady callback that calls initializePlayer() if accessToken exists. Update the init() function to call initializePlayer() after displaying the album (check if window.Spotify is available first). The streaming scope is already in SCOPES.
What does this prompt ask for?
You are telling Claude Code to register your browser as a Spotify Connect device. The Spotify.Player constructor creates the device, and the ready event fires once it is connected and gives you a device_id.
Your togglePlay function already passes deviceId to the play endpoint. Once the SDK fills that variable, the play command targets your browser instead of a random device.
- Let Claude Code generate the changes. It will modify your existing app.js file.
- After Claude Code finishes, verify it added an initializePlayer() function. Look for this key section near the top of that function:
function initializePlayer() {
player = new Spotify.Player({
name: 'Album of the Day',
getOAuthToken: cb => { cb(accessToken); },
volume: 0.5,
});
player.addListener('ready', ({ device_id }) => {
console.log('Ready with Device ID', device_id);
deviceId = device_id;
document.getElementById('status-message').textContent = 'Player ready';
});
// ... error listeners and player_state_changed below ...
player.connect();
}
What does initializePlayer do?
- new Spotify.Player() creates a new playback device in your browser with the name 'Album of the Day'.
- getOAuthToken is a callback the SDK calls whenever it needs a fresh token to stream audio.
- The ready event gives you the device_id that identifies this browser device on Spotify's network.
- player.connect() activates the device and makes it visible to other Spotify clients.
- Also verify Claude Code added this callback after your event listeners:
// SDK ready callback
window.onSpotifyWebPlaybackSDKReady = () => {
if (accessToken) {
initializePlayer();
}
};
Why onSpotifyWebPlaybackSDKReady?
The SDK script loads asynchronously. Spotify calls window.onSpotifyWebPlaybackSDKReady once it is fully loaded and ready to use. Without this callback, you might try to create a player before the SDK is available.
- Finally, check that Claude Code updated the init() function to call initializePlayer() after displaying the album. Look for this pattern:
const album = await getAlbumOfTheDay();
displayAlbum(album);
if (window.Spotify) {
initializePlayer();
}
Let Claude Code handle the details
If the generated code does not match these patterns, describe the mismatch to Claude Code. For example: "The initializePlayer function should log 'Ready with Device ID' in the ready event handler." Claude Code will fix it.
Restart and test in-browser playback
Your local server is still serving the old files. You need to restart it so it picks up the changes Claude Code just made.
- Switch to the Terminal tab where your local server is running.
- Press Ctrl+C to stop the server.
- Restart the server by running:
python3 -m http.server 8000
- Return to Chrome and open http://127.0.0.1:8000.
- You need to re-authenticate because the page reloaded. Click Log in with Spotify and authorize the app.
- Open DevTools by pressing Cmd+Option+J (macOS) or Ctrl+Shift+J (Windows) to see the Console.
Before you click play, what do you expect to see in the console? Do you think the player is already connected?
- Look at the browser console. You should see a message: Ready with Device ID followed by a long string. This confirms the SDK connected successfully.
- Click the Play button.
You should hear the album streaming directly from your browser tab. The status message should show "Player ready" and the button text should switch to "Pause".
Not hearing any audio?
- Check that you are using Chrome. The Web Playback SDK works best in Chrome.
- Verify the console shows "Ready with Device ID". If it shows "Premium account required" instead, your Spotify account needs an active Premium subscription.
- If you see "Authentication error", your token may have expired. Clear localStorage in DevTools (Application tab), then reload and log in again.
- Describe the exact console error to Claude Code and let it troubleshoot.
- Open your Spotify mobile app or desktop app. Tap the Devices Available icon (the speaker/computer icon). You should see "Album of the Day" listed as an active device.
Why does the app appear as a device?
When you called player.connect(), your browser registered itself on Spotify's network with the name you chose ('Album of the Day'). It works just like the Spotify desktop app or a smart speaker. Any Spotify client on your account can see it and transfer playback to it.
Verify the play/pause toggle
- With music playing, click the button (it should now say Pause). The music should stop.
- Click it again (it should now say Play). The music should resume.
The button text updates because the player_state_changed event fires every time playback pauses or resumes, and your handler toggles the label between "Play" and "Pause".
Button text not updating?
- Make sure Claude Code added a player_state_changed listener that updates the button's textContent. If it is missing, tell Claude Code: "Add a player_state_changed listener that updates the play button text based on state.paused."
- If clicking Pause does nothing, check that player.pause() is being called in the togglePlay function's isPlaying branch.
- Ask Claude Code for help debugging your playback toggle.
✔️ Awesome, I've got everything!
Great. Make sure you have saved all files.
ⓧ I'd like to double check the full code
Your app.js should now contain these sections in order. Scroll through your file and confirm each is present:
- Constants (CLIENT_ID, REDIRECT_URI, SCOPES) and state variables (accessToken, player, deviceId, currentAlbumUri, isPlaying).
- PKCE helper functions (generateRandomString, sha256, base64urlencode, generateCodeChallenge).
- Auth functions (login, getToken, refreshToken).
- Album functions (getDateSeed, getAlbumOfTheDay, displayAlbum).
- The new initializePlayer() function with a Spotify.Player constructor, event listeners for ready/not_ready/errors/player_state_changed, and player.connect().
- The togglePlay() function (unchanged from last step).
- Event listeners for login-btn and play-btn.
- The new window.onSpotifyWebPlaybackSDKReady callback that calls initializePlayer() if accessToken exists.
- The init() function, now calling initializePlayer() after displayAlbum(album) with a if (window.Spotify) check.
The index.html and style.css files are unchanged from the previous step.
Your browser is now a full Spotify Connect device. Next up, you will take this working app and make it truly yours by designing a custom look and feel with Claude Code.
Design Your Own Look and Feel
Your app works. It authenticates, fetches a daily album, and streams music directly in the browser.
Right now it looks like every other dark-themed tutorial project. In this step, you will learn to write effective design prompts for Claude Code to transform the UI into something that looks and feels like your own creation.
In this step, get ready to:
- Write a detailed design prompt describing your visual vision.
- Give the prompt to Claude Code and review the generated design.
- Test the full flow and iterate until you are happy.
Write your design prompt
The quality of what Claude Code generates depends entirely on the detail in your prompt. Vague instructions produce generic results.
- Think about what you want the app to look like. Consider these five dimensions: color scheme, typography, layout, animations, and overall mood.
- Write a design prompt for Claude Code that describes your vision in concrete terms. Aim for 2-3 sentences covering the specific visual changes you want.
What makes a good design prompt?
Name specific visual choices instead of abstract qualities. "Warm orange accent color" is better than "make it feel cozy." "Large album art centered with a blurred version as the page background" is better than "make it look cool."
Here is an example prompt you could use as inspiration:
"Redesign the UI with a dark theme inspired by vinyl records, large album art centered on the page, a subtle gradient background that shifts based on the album cover colors, smooth fade-in animations, and minimalist playback controls underneath the album art."
Be specific about what to keep
If there are parts of the current layout you like (the centered card, the button shape, the overall structure), mention them in your prompt. Claude Code may overhaul everything otherwise.
Give your prompt to Claude Code
Now you will hand your design vision to Claude Code and watch it update your files.
- Switch back to the Terminal tab running your Claude Code session.
- Type your design prompt and press Enter. Claude Code will update index.html, style.css, and potentially app.js to match your description.
- When Claude Code asks for permission to edit files, allow it.
- Review the changes it describes. If something is not quite right, give it a follow-up instruction describing what to fix.
How to give good follow-up instructions
Point at the specific element that needs fixing rather than repeating your entire prompt. For example: "Make the play button larger and add a hover glow effect" or "The album title font is too small, increase it to 1.8rem."
Each follow-up should target one or two elements. Stacking too many changes into one message makes it harder for Claude Code to get everything right.
- Refresh your browser at http://127.0.0.1:8000 to see the updated design.
You should see your custom color scheme, typography, or layout changes applied to the login screen.
Page looks the same after refresh?
Your browser may be serving a cached version of style.css. Do a hard refresh with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to bypass the cache.
If the page is blank or broken, check the browser console for errors. Describe the error to Claude Code and it will fix the issue. Help me debug why my page is blank after Claude Code updated the design
Test the full flow and iterate
A design that looks great on the login screen might break something in the album display or playback controls. You need to test the entire flow end to end.
- Click the login button and authorize with Spotify.
- Confirm that today's album displays with its cover art, title, artist name, and release year. All text should be readable against your new background.
- Click Play and confirm the album streams in your browser. The play/pause toggle should still work.
Before you declare it done, ask yourself: does every element feel intentional? Is the album art the focal point?
- If any element looks off, switch back to Claude Code and give it a targeted follow-up prompt describing what to change.
- After each round of changes, hard-refresh your browser and test the full login-to-playback flow again.
- Repeat until you are satisfied with how the app looks and everything still works.
Why iterate in small rounds?
Each prompt-and-check cycle gives you a visible delta to evaluate. If something breaks, you know exactly which change caused it. Batching too many design changes into one prompt makes it hard to identify what went wrong.
Ideas if you are stuck
- Try a vinyl record theme with circular album art and a spinning animation on play.
- Try a retro cassette tape look with pixel fonts and neon accents.
- Try a minimalist magazine layout with serif typography and lots of whitespace.
- Try extracting the dominant color from the album art and using it as a background gradient.
You now have a fully functional, custom-designed Album of the Day player. You built it entirely through natural language prompts. Next up: a secret mission to add track-by-track navigation.
Secret mission
Add Track-by-Track Navigation
Your album player works, but it always starts from track one with no way to skip around. In this secret mission, you will prompt Claude Code to add a full track list with next/previous buttons and click-to-jump, so you can navigate the album like a real music player.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing cloud costs. Your Spotify Developer app is free and stays within Development Mode (limited to 5 users, which is fine for personal use).
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- Spotify Developer app (on the Spotify Developer Dashboard).
- Project folder on your Desktop (containing index.html, style.css, and app.js).
- Claude Code CLI (installed via the native installer).
Keep everything running
No action needed. Choose this if you plan to keep using your Album of the Day app.
- Your Spotify Developer app stays active in Development Mode at no cost.
- Your project folder stays on your Desktop. Run python3 -m http.server 8000 from inside it anytime to use the app.
- Claude Code remains installed on your machine. It uses no resources when not running.
Pause - I'll come back to this later
Nothing is running when your local server is stopped, so there is nothing to pause.
- If your local server is still running in Terminal, press Ctrl+C to stop it.
- Your project files and Spotify Developer app remain intact for next time.
Delete - I don't want to use this again
Remove all project resources and start fresh.
- Stop the local server if it is still running by pressing Ctrl+C in the Terminal window.
- Delete your project folder by running this command in Terminal:
rm -rf ~/Desktop/album-of-the-day
Your folder name may differ
Replace album-of-the-day with whatever you named your project folder in Step 1.
- Delete your Spotify Developer app by opening the Spotify Developer Dashboard at https://developer.spotify.com/dashboard.
- Click the name of your app to open its overview page.
- Click the red DELETE button and confirm the deletion.
- Remove Claude Code from your machine by running these commands in Terminal:
rm -f ~/.local/bin/claude
rm -rf ~/.local/share/claude
- Remove Claude Code configuration and session data by running:
rm -rf ~/.claude
rm -f ~/.claude.json
Nice Work!
Nice Work!
You just built a personal Album of the Day web app that authenticates with Spotify, picks a daily random album, and streams it directly in your browser. Every line of code came from prompting Claude Code with natural language.
You've learned how to:
- Build a complete web application using Claude Code prompts and natural language descriptions, generating an entire OAuth 2.0 PKCE authentication flow, API integration, and playback system from scratch.
- Integrate the Spotify Web API to search for albums, control playback, and solve the "no active device" problem by turning your browser into a Spotify Connect device with the Web Playback SDK.
- Write effective design prompts for Claude Code to transform a functional app into a custom-styled UI that matches your personal vision.
- Secret Mission: Added track-by-track navigation with a live-updating track list and skip controls powered by the SDK's player_state_changed event.
Ready to quiz yourself?