Skip to main content

Detailed Setup Guide

This guide covers everything you need to set up Player2, from Spotify Developer credentials to deployment.

Spotify Developer Setup

Creating a Spotify App

1

Access Spotify Developer Dashboard

Navigate to the Spotify Developer Dashboard and log in with your Spotify account.
2

Create New App

Click “Create App” and fill in the required information:
  • App Name: Player2 (or your preferred name)
  • App Description: Enhanced Spotify music player with lyrics
  • Redirect URI: http://localhost:5173
  • API: Select Web API
For production deployments, add your production URL (e.g., https://yourdomain.com) to the Redirect URIs list.
3

Get Your Credentials

After creating the app:
  1. Click on your newly created app
  2. Click “Settings”
  3. Copy your Client ID
  4. You can also view your Client Secret (though Player2 uses implicit grant flow and doesn’t require it)
Never commit your Client ID or Client Secret to version control. Always use environment variables.

Environment Configuration

Required Environment Variables

Player2 uses Vite’s environment variable system. Create a .env file in your project root:
.env
VITE_SPOTIFY_CLIENT_ID=your_spotify_client_id
VITE_SPOTIFY_REDIRECT_URI=http://localhost:5173
Vite requires environment variables to be prefixed with VITE_ to be exposed to the client-side code.

Environment Variable Reference

VariableRequiredDescriptionExample
VITE_SPOTIFY_CLIENT_IDYesYour Spotify App Client ID16d98594b10949eb9aed4628a58b37e8
VITE_SPOTIFY_REDIRECT_URIYesRedirect URI for OAuthhttp://localhost:5173

Loading Environment Variables

Player2 loads these variables in the SpotifyContext:
src/contexts/SpotifyContext.tsx
const CLIENT_ID = import.meta.env.VITE_SPOTIFY_CLIENT_ID;
const REDIRECT_URI = import.meta.env.VITE_SPOTIFY_REDIRECT_URI;
const SCOPES = [
  'user-read-playback-state',
  'user-modify-playback-state', 
  'user-library-read'
];

Project Structure

Key Directories and Files

player2/
├── src/
│   ├── App.tsx                    # Main application component
│   ├── main.tsx                   # Application entry point
│   ├── components/
│   │   ├── LyricsDisplay.tsx      # Synchronized lyrics component
│   │   ├── Search.tsx             # Music search interface
│   │   ├── QueueDrawer.tsx        # Queue management
│   │   ├── DynamicBackground.tsx  # Color-adaptive background
│   │   └── ContextMenu.tsx        # Right-click context menu
│   ├── contexts/
│   │   ├── SpotifyContext.tsx     # Spotify SDK and playback state
│   │   └── LyricsContext.tsx      # Lyrics visibility state
│   ├── hooks/
│   │   └── useDebounce.ts         # Debounce hook for search
│   └── types.ts                   # TypeScript type definitions
├── .env                           # Environment variables (create this)
├── .env.example                   # Example environment file
├── package.json                   # Dependencies and scripts
├── vite.config.ts                 # Vite configuration
└── tailwind.config.js             # TailwindCSS configuration

Core Components

Spotify Context Provider

The SpotifyContext manages all Spotify-related state and functionality:
SpotifyProvider usage
import { SpotifyProvider, useSpotify } from './contexts/SpotifyContext';

function App() {
  return (
    <SpotifyProvider>
      <YourComponents />
    </SpotifyProvider>
  );
}

// In any child component
function Player() {
  const { currentTrack, isPlaying, sdk } = useSpotify();
  // Access current track, playback state, and SDK methods
}

Available Context Values

Context API
interface SpotifyContextType {
  sdk: SpotifyApi | null;              // Spotify SDK instance
  currentTrack: SpotifyTrack | null;   // Currently playing track
  isPlaying: boolean;                  // Playback state
  progress: number;                    // Current position (ms)
  duration: number;                    // Track duration (ms)
  error: string | null;                // Error message if any
  queue: SpotifyTrack[];               // Current queue
  lyrics: LyricsResponse | null;       // Synchronized lyrics
  togglePlayback: () => Promise<void>; // Play/pause function
  refreshQueue: () => Promise<void>;   // Refresh queue function
}

Key Features Implementation

Real-Time Lyrics

Lyrics are fetched from LRCLIB with intelligent caching and prefetching:
Lyrics implementation
// Lyrics are automatically fetched when track changes
const fetchLyrics = async (track: SpotifyTrack) => {
  const query = new URLSearchParams({
    artist_name: track.artists[0].name,
    track_name: track.name,
    duration: (track.duration_ms / 1000).toString()
  });

  const res = await fetch(`https://lrclib.net/api/get?${query}`);
  const data = await res.json();
  
  // Parse LRC format into synchronized line objects
  return parseLrcLyrics(data.syncedLyrics);
};
Lyrics are cached in memory to prevent redundant API calls. The next track’s lyrics are prefetched 10 seconds before the current track ends.

Dynamic Color Extraction

Album art colors are extracted using ColorThief and applied to the UI:
Color extraction
import ColorThief from 'colorthief';

const img = new Image();
img.crossOrigin = 'Anonymous';
img.src = currentTrack?.album?.images[0]?.url;

img.onload = () => {
  const colorThief = new ColorThief();
  const dominantColor = colorThief.getColor(img);
  
  // Apply to CSS custom property
  document.documentElement.style.setProperty(
    '--color', 
    `rgb(${dominantColor.toString()})`
  );
};

Keyboard Shortcuts

Keyboard controls are implemented for quick playback control:
Keyboard controls
useEffect(() => {
  const handleKeyDown = (event: KeyboardEvent) => {
    const { key } = event;

    if (key === "ArrowLeft") {
      sdk?.player.skipToPrevious();
    } else if (key === "ArrowRight") {
      sdk?.player.skipToNext();
    } else if (key === "Space") {
      isPlaying ? 
        sdk?.player.pausePlayback() : 
        sdk?.player.startResumePlayback();
    }
  };

  window.addEventListener("keydown", handleKeyDown);
  return () => window.removeEventListener("keydown", handleKeyDown);
}, [isPlaying]);

Development Workflow

Available Scripts

package.json scripts
{
  "scripts": {
    "dev": "vite",              // Start development server
    "build": "vite build",      // Build for production
    "lint": "eslint .",         // Run ESLint
    "preview": "vite preview"   // Preview production build
  }
}

Development Server

Start the development server with hot module replacement:
npm run dev
The server runs on http://localhost:5173 by default.

Linting

Run ESLint to check for code quality issues:
npm run lint

Building for Production

Creating an Optimized Build

1

Update Environment Variables

Update your .env file with production values:
.env.production
VITE_SPOTIFY_CLIENT_ID=your_client_id
VITE_SPOTIFY_REDIRECT_URI=https://yourdomain.com
2

Build the Application

npm run build
This generates optimized static files in the dist/ directory.
3

Test the Production Build

npm run preview

Build Output

The production build is optimized with:
  • Code splitting - Smaller initial bundle size
  • Tree shaking - Removes unused code
  • Minification - Compressed JavaScript and CSS
  • Asset optimization - Optimized images and fonts

Deployment Options

Vercel

1

Install Vercel CLI

npm i -g vercel
2

Deploy

vercel
3

Add Environment Variables

In your Vercel dashboard, add:
  • VITE_SPOTIFY_CLIENT_ID
  • VITE_SPOTIFY_REDIRECT_URI
4

Update Spotify Redirect URI

Add your Vercel URL to the Redirect URIs in your Spotify Developer Dashboard.

Netlify

1

Connect Repository

Connect your Git repository to Netlify.
2

Configure Build Settings

  • Build command: npm run build
  • Publish directory: dist
3

Add Environment Variables

In Site settings → Environment variables, add your Spotify credentials.

Static Hosting

Deploy the dist/ folder to any static hosting service:
  • AWS S3 + CloudFront
  • GitHub Pages
  • Firebase Hosting
  • Cloudflare Pages
Remember to update your Spotify App’s Redirect URIs to include your production domain!

Troubleshooting

Common Issues

If you encounter build errors:
  1. Delete node_modules and reinstall:
    rm -rf node_modules package-lock.json
    npm install
    
  2. Clear Vite cache:
    rm -rf .vite
    
  3. Check Node.js version (requires v16+):
    node --version
    
If you see CORS errors with Spotify API:
  1. Verify your Redirect URI matches exactly
  2. Ensure you’re using http://localhost:5173 (not 127.0.0.1)
  3. Clear browser cache and cookies
If lyrics don’t appear:
  1. Check browser console for LRCLIB API errors
  2. Verify the track has synchronized lyrics available
  3. Check network tab for failed requests
If colors aren’t updating:
  1. Check if album art URL is accessible
  2. Verify CORS headers allow image loading
  3. Check console for ColorThief errors

Advanced Configuration

Customizing Vite Config

Modify vite.config.ts for advanced build options:
vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    host: true // Expose to network
  },
  build: {
    outDir: 'dist',
    sourcemap: true // Generate source maps
  }
});

TailwindCSS Configuration

Customize the design system in tailwind.config.js:
tailwind.config.js
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        // Add custom colors
      },
      animation: {
        // Add custom animations
      }
    }
  },
  plugins: []
};

Next Steps

Back to Introduction

Learn more about Player2’s features

Quick Start

Get started quickly

Build docs developers (and LLMs) love