DEV Community

Cover image for 🎡 Build a Real-Time Spotify Dashboard with Next.js (Part 1: The Auth)
Aditya Thakekar
Aditya Thakekar

Posted on

🎡 Build a Real-Time Spotify Dashboard with Next.js (Part 1: The Auth)

Series: Project Spotiviz
Tags: #nextjs #webdev #tutorial #security

http://googleusercontent.com/image_generation_content/0

Spotify

πŸ‘‹ The "Why."

We all love Spotify Wrapped. It is a brilliant piece of product marketing that turns data into a cultural event. But as developers, waiting 12 months to see our listening habits feels like an eternity.

Why can't we see our data **now?

Welcome to Project Spotiviz. In this three-part series, we aren't just going to fetch a JSON file. We are going to engineer a production-ready, full-stack application that visualizes your music taste in real-time.

What we are building today:
We are ignoring the charts for a moment. Today, we focus on the gatekeeper: Authentication. πŸ”

The Goal: By the end of this article, you will have a secure backend that can handshake with Spotify, exchange secret codes for access tokens, and store them in secure, HTTP-only cookies that client-side scripts can't touch.


πŸ›οΈ The Architecture

Architecture

Before we write code, we must understand the flow. Using a third-party API like Spotify isn't as simple as fetch('https://api.spotify.com'). We are dealing with private user data.

We are using the Authorization Code Flow. This is robust and allows us to get a "Refresh Token," meaning our app can stay logged in forever without the user needing to re-approve it every hour.

http://googleusercontent.com/image_generation_content/1

πŸ› οΈ The Stack

  • Framework: Next.js 14/15 (App Router)
  • Language: TypeScript
  • Styling: Tailwind CSS
  • State Management: Server-Side Cookies

Phase 1: The Spotify Developer Dashboard

Developer-dashboard

We need to register our application with Spotify to get our credentials.

  1. Log in to the Spotify Developer Dashboard.
  2. Click Create App.
  3. Give it a name (e.g., Spotiviz Local).
  4. 🚨 Crucial Step: You will see a field for Redirect URIs. This is a whitelist of URLs that Spotify is allowed to return data to. If you don't set this exactly right, the API will block you.

http://googleusercontent.com/image_generation_content/2

Input this exactly:
http://localhost:3000/api/callback


Phase 2: Project Setup & Secrets 🀫

Open your terminal. Let’s scaffold a robust Next.js project.

npx create-next-app@latest spotiviz
# Select Yes for TypeScript, Tailwind, ESLint, App Router
Enter fullscreen mode Exit fullscreen mode

Managing Secrets

We need to store our credentials securely. Create a file named .env.local in the root of your project.

http://googleusercontent.com/image_generation_content/4

# .env.local
SPOTIFY_CLIENT_ID=your_client_id_paste_here
SPOTIFY_CLIENT_SECRET=your_client_secret_paste_here
SPOTIFY_REDIRECT_URI=http://localhost:3000/api/callback
Enter fullscreen mode Exit fullscreen mode

Phase 3: The Authorization URL πŸ”—

We need a button that kicks off the process. We need to construct a specific URL that tells Spotify exactly what permissions (Scopes) we want.

Create a utility library: lib/spotify.ts

const scopes = [
  "user-read-recently-played",
  "user-top-read",
  "user-read-currently-playing",
  "user-library-read"
].join(" ");

const params = {
  scope: scopes,
  response_type: "code",
  redirect_uri: process.env.SPOTIFY_REDIRECT_URI!,
  client_id: process.env.SPOTIFY_CLIENT_ID!,
};

const queryParamString = new URLSearchParams(params).toString();

export const LOGIN_URL = `https://accounts.spotify.com/authorize?${queryParamString}`;
Enter fullscreen mode Exit fullscreen mode

Pro Tip: If you forget to ask for a specific scope here (like user-top-read), the API will return a 403 Forbidden error later when you try to fetch that data.


Phase 4: The "Handshake" (API Route) 🀝

Handshake

This is the most critical part of the application.

Spotify redirects the user to http://localhost:3000/api/callback?code=AQDa.... That code is NOT the access token. It is a temporary authorization code.

We must exchange this code Server-Side using a Next.js Route Handler.

File: app/api/callback/route.ts

import { NextResponse } from "next/server";
import { cookies } from "next/headers";

export async function GET(request: Request) {
  // 1. Parse the URL to get the "code" parameter
  const { searchParams } = new URL(request.url);
  const code = searchParams.get("code");

  if (!code) {
    return NextResponse.json({ error: "No code provided" }, { status: 400 });
  }

  // 2. Prepare the request to exchange code for a token
  const authOptions = {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      Authorization:
        "Basic " +
        Buffer.from(
          process.env.SPOTIFY_CLIENT_ID + ":" + process.env.SPOTIFY_CLIENT_SECRET
        ).toString("base64"),
    },
    body: new URLSearchParams({
      code: code,
      redirect_uri: process.env.SPOTIFY_REDIRECT_URI!,
      grant_type: "authorization_code",
    }).toString(),
  };

  try {
    const response = await fetch("[https://accounts.spotify.com/api/token](https://accounts.spotify.com/api/token)", authOptions);
    const data = await response.json();

    // 3. Securely store the tokens in Cookies πŸͺ
    const cookieStore = cookies();

    cookieStore.set("spotify_access_token", data.access_token, {
      httpOnly: true, // Prevents JavaScript access (XSS protection)
      secure: process.env.NODE_ENV === "production",
      maxAge: 3600,
      path: "/",
    });

    return NextResponse.redirect(new URL("/dashboard", request.url));

  } catch (error) {
    return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ”’ Deep Dive: The Cookie Strategy

Code
Why did we use httpOnly: true?

If we stored the token in localStorage, a malicious chrome extension could steal the user's session. With HttpOnly cookies, the browser stores the cookie and attaches it to requests, but JavaScript cannot read it.

http://googleusercontent.com/image_generation_content/3


πŸš€ Testing The Flow

  1. Run npm run dev.
  2. Click your login button.
  3. Accept the permissions on Spotify's side.
  4. Open your browser Developer Tools > Application > Cookies.

You should see your secure token sitting there, ready for Part 2.

What's Next?

In Part 2, we will:

  1. Create the /dashboard page.
  2. Handle Token Refresh (keeping the user logged in).
  3. Transform raw JSON into beautiful charts.

If you found this helpful, drop a comment or a reaction! I'm building this live, so follow along for the next update.

Some really cool YouTube videos

  1. Programming with Mosh. * Video: How to build a REST API with Node js & Express
    Why it's great: A comprehensive 1-hour walkthrough on building a REST API from scratch.

  2. Fireship Video: RESTful APIs in 100 Seconds // Build an API from Scratch with Node.js Express Why it's great: A fast-paced, high-level overview combined with a practical example.

  3. Traversy Media Video: Learn The MERN Stack - Express & MongoDB Rest API
    Why it's great: A full crash course on building a backend API using the popular MERN stack (MongoDB, Express, React, Node).

  4. Hussein Nasser Video: gRPC Crash Course - Modes, Examples, Pros & Cons and more
    Why it's great: An in-depth engineering look at gRPC, including its pros and cons compared to REST.

Top comments (0)