Spotify Data Parsing

Spotify data parsing example. Typebulb gives the AI assistant a summarized view of the data tab. This ensures the AI sees the structure of the data without wasting its context window. AIs are inc...

code.tsx

import React from "react";
import { createRoot } from "react-dom/client"

interface SpotifyArtist {
  name: string;
  external_urls: { spotify: string };
}

interface SpotifyImage {
  url: string;
  height: number;
  width: number;
}

interface SpotifyTrack {
  id: string;
  name: string;
  track_number: number;
  duration_ms: number;
  explicit: boolean;
  artists: SpotifyArtist[];
}

interface SpotifyAlbum {
  name: string;
  album_type: string;
  release_date: string;
  total_tracks: number;
  images: SpotifyImage[];
  artists: SpotifyArtist[];
  tracks: {
    items: SpotifyTrack[];
  };
}

function formatDuration(ms: number) {
  const minutes = Math.floor(ms / 60000);
  const seconds = ((ms % 60000) / 1000).toFixed(0);
  return `${minutes}:${Number(seconds) < 10 ? '0' : ''}${seconds}`;
}

function App() {
  const data = React.useMemo(() => {
    try {
      return tb.json<SpotifyAlbum>(0);
    } catch (e) {
      console.error("Failed to parse data", e);
      return null;
    }
  }, []);

  if (!data) {
    return <div className="container">Error loading album data.</div>;
  }

  const mainArtist = data.artists[0];
  const coverArt = data.images[0]?.url;
  const releaseYear = new Date(data.release_date).getFullYear();

  return (
    <div className="container">
      <header className="album-header">
        <img src={coverArt} alt={data.name} className="album-art" />
        <div className="album-info">
          <div className="album-meta" style={{ textTransform: 'uppercase', fontSize: '0.75rem', marginBottom: '0.5rem' }}>
            {data.album_type}
          </div>
          <h1>{data.name}</h1>
          <div className="album-meta">
            <a href={mainArtist.external_urls.spotify} className="artist-link" target="_blank" rel="noreferrer">
              {mainArtist.name}
            </a>
            <span className="meta-separator">{releaseYear}</span>
            <span className="meta-separator">{data.total_tracks} songs</span>
          </div>
        </div>
      </header>

      <div className="tracklist">
        {data.tracks.items.map((track) => (
          <div key={track.id} className="track-item">
            <div className="track-number">{track.track_number}</div>
            <div className="track-main">
              <div className="track-name">
                {track.name}
                {track.explicit && <span className="explicit-badge">E</span>}
              </div>
              <div className="track-artist">
                {track.artists.map(a => a.name).join(", ")}
              </div>
            </div>
            <div className="track-duration">
              {formatDuration(track.duration_ms)}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

const container = document.getElementById("root")
const root = createRoot(container!)
root.render(<App />)

Markdown source · More bulbs by samples · Typebulb home