Quickstart Guide
Get Beat App up and running on your local machine in just a few minutes. This guide will walk you through the essential steps to start streaming music.
Prerequisites : Node.js v18 or higher and npm/yarn/pnpm installed on your system.
Installation
Clone the repository
First, clone the Beat App repository to your local machine: git clone https://github.com/yourusername/beat-app.git
cd beat-app
Install dependencies
Install the required npm packages using your preferred package manager:
Configure environment variables
Copy the example environment file and configure your API credentials: Edit the .env file with your API credentials: VITE_API_URL = http://localhost:3000
VITE_YOUTUBE_API_TOKEN = your_token_here
You’ll need a valid YouTube Music API token to stream music. Contact your API provider for credentials.
Start the development server
Launch the Vite development server: The app will start at http://localhost:5173 by default.
Your First Music Search
Once the development server is running, try these actions:
Open the app
Navigate to http://localhost:5173 in your browser.
Search for a track
Use the search bar in the top navigation to search for your favorite artist or song.
Start playing
Click on any track to start playback. The player controls will appear at the bottom of the screen.
Manage your queue
Click the queue icon to open the queue drawer and see upcoming tracks. You can:
Add tracks to the queue
Play tracks next
Reorder the queue
Understanding the Player Store
Beat App uses Nanostores for state management. Here’s how the player store works:
// src/stores/playerStore.js
import { map } from "nanostores" ;
import audioEl from "../audioEl" ;
const initialState = {
isPlaying: false ,
currentTrackIndex: - 1 ,
currentTrack: null ,
queue: [],
isLoading: false ,
currentTime: 0 ,
duration: 0 ,
isQueueOpen: false ,
};
export const playerStore = map ( initialState );
export const playerActions = {
playTrack : async ( track , newQueue = null ) => {
playerStore . setKey ( "currentTrack" , track );
playerStore . setKey ( "isLoading" , true );
if ( newQueue ) {
playerStore . setKey ( "queue" , newQueue );
}
const audioUrl = await getAudioUrl ( track . trackId );
audioEl . src = audioUrl ;
audioEl . play ();
},
togglePause : () => {
if ( audioEl . paused ) audioEl . play ();
else audioEl . pause ();
},
addToQueue : ( track ) => {
const state = playerStore . get ();
playerStore . setKey ( "queue" , [ ... state . queue , track ]);
},
};
The player store automatically syncs with the HTML5 Audio element and updates the Media Session API for native OS controls.
Using the Player in Components
Access player state and actions in any React component:
import { useStore } from '@nanostores/react' ;
import { playerStore , playerActions } from '../stores/playerStore' ;
function TrackItem ({ track }) {
const { currentTrack , isPlaying } = useStore ( playerStore );
const isCurrentTrack = currentTrack ?. trackId === track . trackId ;
const handlePlay = () => {
playerActions . playTrack ( track , [ track ]);
};
const handleAddToQueue = () => {
playerActions . addToQueue ( track );
};
return (
< div >
< h3 > { track . title } </ h3 >
< p > { track . artists [ 0 ]?. name } </ p >
< button onClick = { handlePlay } >
{ isCurrentTrack && isPlaying ? 'Pause' : 'Play' }
</ button >
< button onClick = { handleAddToQueue } > Add to Queue </ button >
</ div >
);
}
Searching for Music
The YouTube API service provides comprehensive search capabilities:
// src/services/youtube-api.js
import axios from 'axios' ;
import { YOUTUBE_API } from '../constants' ;
const HEADERS = {
Authorization: `Bearer ${ import . meta . env . VITE_YOUTUBE_API_TOKEN } `
};
export async function searchTracks ( query ) {
try {
const res = await axios . get ( ` ${ YOUTUBE_API } /search` , {
params: { q: query , filter: 'SONG' },
headers: HEADERS
});
return {
tracks: ( res . data . data ?. items || []). map ( mapSong ),
continuation: res . data . data ?. continuation
};
} catch ( e ) {
return { tracks: [] };
}
}
export async function searchAlbums ( query ) {
try {
const res = await axios . get ( ` ${ YOUTUBE_API } /search` , {
params: { q: query , filter: 'ALBUM' },
headers: HEADERS
});
return { albums: ( res . data . data ?. items || []). map ( mapAlbum ) };
} catch ( e ) {
return { albums: [] };
}
}
export async function searchArtists ( query ) {
try {
const res = await axios . get ( ` ${ YOUTUBE_API } /search` , {
params: { q: query , filter: 'ARTIST' },
headers: HEADERS
});
return { artists: ( res . data . data ?. items || []). map ( mapArtist ) };
} catch ( e ) {
return { artists: [] };
}
}
Key Features to Explore
Search System Search for tracks, albums, artists, and playlists with dedicated result pages
Queue Management Build and manage your playback queue with play next/add to queue options
Media Controls Control playback from your keyboard, OS media controls, or lock screen
Theme Toggle Switch between light and dark modes with the theme toggle button
Next Steps
Installation Guide Learn about advanced installation options and production builds
API Reference Explore the complete API service and store documentation
Deployment Deploy Beat App to production with Docker and NGINX
Architecture Discover the component structure and architecture
Having issues? Check the browser console for error messages and ensure your API credentials are correctly configured.