← Back to writing
Projects94 visits

Spotify Dashboard (Night City Theme)

Turning Spotify listening data into a fun, interactive music dashboard.

I wanted my top musics to be presented beautifully, in a unique way. So I drew a scene with Affinity and turned my Spotify data into part of the artwork. Welcome to Night City 🌃🎧.

🔎 Overview

  • Goal: Explore music taste through an artsy, interactive dashboard instead of plain charts.
  • Use cases: See favorite artists, top-ranked tracks, genres, and popularity patterns.
  • Tech stack: React, TypeScript, Vite, D3.js, Python, and Pandas.
  • Data source: Spotify track and artist CSV exports (999 ranked tracks and 439 artists).
  • Main features: Illustrated charts, artist/genre filters, and a Spotify music player.
  • Visual style: My own illustrations drawn in Affinity, a moon made with CSS, and D3.js charts customized to fit the art.
  • Architecture: A static website. No backend needs to be running.

🗺️ How Everything Connects

flowchart TD
    A[Spotify Track CSV] --> C[Python + Pandas]
    B[Spotify Artist CSV] --> C
    C --> D[Merged Spotify CSV]
    D --> E[React + D3.js]
    E --> F[Starry Sky - Scatter Plot]
    E --> G[CSS Moon - Pie Chart]
    E --> H[Building - Bar Chart]
    E --> I[Spotify Embed Player]

The simple version: Spotify data → Python cleanup → React dashboard → interactive charts and music. Easy!

🔁 From CSV to Night Sky

  1. Export: Get Spotify track rankings and artist info as CSV files.
  2. Merge: A small Python + Pandas script joins them using the primary artist’s ID. I made sure the merge keeps the original ranking order of the tracks, because a dashboard about “top songs” with shuffled ranks would be… not great 😅.
  3. Load: React reads the merged CSV when the page opens.
  4. Visualize: D3.js shapes and fine-tunes the charts so they fit the illustrations.
  5. Explore: Click artists, genres, or tracks to filter the view or start playing a song.

📊 What’s in the Dashboard?

Feature What it shows Why it’s useful
Starry-sky scatter plot Up to 50 tracks, plotted against track/artist popularity Spot hits and hidden gems
Moon pie chart Top 5 artists by rank-weighted score See which artists stand out
Building bar chart Top 5 primary genres by rank-weighted score Understand your genre preferences
Interactive filters Selected artist or genre Narrow down the charts
Spotify player Embedded track playback Listen while exploring

🎨 The Artsy Part

This is my favorite bit!

  • Hand-drawn artwork: I drew all the illustrations myself in Affinity so the dashboard would have its own personality.
  • Charts that blend in: I used D3.js to tweak positions, styles, and interactions until the data felt like part of the drawing, not something pasted on top.
Art element Chart Creative idea
Moon (CSS) Pie chart A CSS-made moon turns the artist breakdown into a playful visual.
Starry sky Scatter plot Data points blend into the illustrated night sky like stars.
Building Bar chart The bars fit into the building illustration instead of looking like a standard chart.

The whole idea: it should feel like exploring an illustration, not reading a spreadsheet ✨.

🔭 Okay, But How Do I Read It?

Chart How to read it What it tells you
Starry sky / scatter plot Higher = more popular artist. Right = track is more popular relative to its artist; left = less popular relative to its artist. Find standout tracks, big artists, and underrated songs.
Moon / pie chart A larger slice means the artist contributes more to the ranking score. Which artists dominate your top-ranked songs.
Building / bar chart A taller bar means the genre has a higher combined ranking score. Which music styles appear strongest in your rankings.
Filters Select an artist or genre to focus the charts on matching tracks. Compare a specific artist or style with the wider collection.

Quick example: The #1 track gets a score of 1 / 1 = 1.00, while track #10 gets 1 / 10 = 0.10. So higher-ranked songs carry more weight in the moon and building charts.

Small but important note: These are rank-weighted insights, not actual play counts or listening minutes. The genre chart uses each artist’s first listed genre, and everything reflects the CSV snapshot I used.

🤔 Decisions I Made (and What They Cost)

Area Decision Trade-off
Frontend React + TypeScript Flexible, but adds component code
Charts D3.js Custom visuals, more setup
Art direction My Affinity illustrations + CSS moon Personal look, but more styling work
Data processing Python + Pandas Easy to merge, but refresh is manual
Storage Static CSV No database, but no live data
Playback Spotify Embed Simple integration, relies on Spotify
Hosting Static deployment Easy to run, but updating data needs a new build

💸 Cost & Performance

  • Static hosting: No always-on server or database eating money.
  • Smaller files: Drop unused CSV columns to shrink the download.
  • Chart limits: Show fewer points so things stay smooth.
  • Browser caching: Cache static files so repeat visits load faster.
  • Data refresh: Only rebuild when there’s a new Spotify export.

🔮 What’s Next?

Spoiler: I already started on the “live data” part 👀. There’s an Express + TypeScript backend in the repo with Spotify OAuth login and token refresh, plus a token interceptor on the frontend. It’s not powering the live site yet, but it’s the groundwork for pulling fresh data instead of CSV snapshots.

Other ideas on my list:

Extension Change Benefit
Spotify API Add authenticated data fetching Fresher listening information
More filters Filter by year or popularity Deeper exploration
Listening trends Compare ranking snapshots See changes over time
Database Save past datasets Track long-term preferences
Mobile design Improve responsive charts Better phone experience

📝 Design Journal, in a Nutshell

  • Problem: Normal Spotify rankings are no fun to explore.
  • Solution: Turn them into an artsy dashboard with interactive charts and music playback.
  • Choice: My Affinity artwork + a CSS moon for the scenery, D3.js for chart tweaks, and Python for data prep.
  • Trade-off: Lightweight and easy to host, but not real-time (yet!).
  • Next step: Better data quality and live integration.

💬 Closing

This project taught me that data storytelling can be fun and pretty. Hand-drawn scenes, a bit of CSS, and D3.js turned a simple Spotify dataset into something I actually want to explore.

Put on your headphones and take a little night walk with me 🌙🎶