### Application Setup with Expo Router (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Configures the entire application, including routing and authentication flow using Expo Router. It sets up authentication providers and defines the navigation structure, showing a sign-in modal if the user is not authenticated.
```tsx
// src/app/_layout.tsx
import Stack from "@/components/ui/Stack";
import { SpotifyClientAuthProvider, useSpotifyAuth } from "@/lib/spotify-auth/spotify-client-provider";
import { SpotifyActionsProvider } from "@/components/api";
import { Modal } from "@/components/modal";
import SignInRoute from "@/components/sign-in";
import { makeRedirectUri } from "expo-auth-session";
const redirectUri = makeRedirectUri({ scheme: "exspotify" });
export default function RootLayout() {
return (
);
}
function AuthenticatedApp() {
const spotifyAuth = useSpotifyAuth();
return (
<>
{/* Show login modal when not authenticated */}
>
);
}
```
--------------------------------
### Get Playlist Details with Server Actions
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Fetches complete playlist data, including tracks and owner information, using server actions. It returns a React component with detailed playlist metadata, owner profile, and track listing.
```tsx
import { renderPlaylistAsync } from "@/components/spotify/spotify-server-actions";
const playlistView = await renderPlaylistAsync({
playlistId: "37i9dQZF1DXcBWIGoYBM5M",
});
// Returns component with:
// - Playlist metadata (name, description, track count)
// - Owner profile (avatar, display name, followers)
// - Complete track listing with album art
// - External Spotify links
```
--------------------------------
### Spotify API Environment Configuration (Bash/TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Defines the necessary environment variables for Spotify API integration. Client ID is exposed publicly, while the client secret is strictly for server-side use to maintain security.
```bash
# .env file
EXPO_PUBLIC_SPOTIFY_CLIENT_ID=your_client_id_here
SPOTIFY_CLIENT_SECRET=your_client_secret_here
```
```tsx
// Access in code
const clientId = process.env.EXPO_PUBLIC_SPOTIFY_CLIENT_ID;
const clientSecret = process.env.SPOTIFY_CLIENT_SECRET; // Server-only
// Client secret is NEVER exposed to client bundles
// Only used in server actions marked with "use server"
```
--------------------------------
### Create Spotify API Client with Auto-Authentication (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Creates a Spotify API client that wraps server actions, injecting authentication automatically and caching results. This simplifies API interactions by handling token management and refreshing behind the scenes. The provider should be set up at the application root.
```tsx
import { createSpotifyAPI } from "@/components/spotify/create-spotify-client-api";
import * as serverActions from "@/components/spotify/spotify-server-actions";
const api = createSpotifyAPI(serverActions);
// Setup provider at app root
function App() {
return (
);
}
// Use in any child component
function SearchPage() {
const spotify = api.useSpotify();
const handleSearch = async () => {
// Automatically includes auth token, refreshes if expired
// Results cached for 60 seconds
const results = await spotify.renderSongsAsync({
query: "radiohead",
limit: 20,
});
return results;
};
}
```
--------------------------------
### Spotify API Environment Variables
Source: https://github.com/evanbacon/expo-router-spotify/blob/main/README.md
Required environment variables for connecting to the Spotify API. The client ID is public, while the client secret must remain private on the server to prevent unauthorized access.
```dotenv
EXPO_PUBLIC_SPOTIFY_CLIENT_ID=xxx
SPOTIFY_CLIENT_SECRET=xxx
```
--------------------------------
### Fetch User Playlists with Server Actions
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Retrieves the authenticated user's playlists using server actions, supporting pagination. It returns a server component displaying playlist information or a message if no playlists are found.
```tsx
import { getUserPlaylists } from "@/components/spotify/spotify-server-actions";
// Get first 20 playlists (default)
const playlists = await getUserPlaylists({});
// Paginated fetch
const nextPage = await getUserPlaylists({
limit: 50,
offset: 20,
});
// Returns component or "No playlists found" message
// Each playlist includes: name, description, image, owner details
```
--------------------------------
### Search Spotify Tracks, Artists, and Albums with Server Actions
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Fetches search results from Spotify's API using server actions. It supports querying multiple entity types and configurable result limits, returning pre-rendered React components with relevant data.
```tsx
import { renderSongsAsync } from "@/components/spotify/spotify-server-actions";
// Basic search with default limit (10 items)
const searchResults = await renderSongsAsync({
query: "drake",
});
// Search with custom limit
const moreResults = await renderSongsAsync({
query: "the beatles",
limit: 25,
});
// Returns a component pre-rendered with:
// - Artists with images, follower counts
// - Tracks with album art, artist names
// - Albums with artwork and metadata
```
--------------------------------
### Spotify OAuth Provider Configuration
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Manages the Spotify OAuth flow with automatic token refresh and localStorage persistence. It configures the authentication provider with client ID, scopes, and redirect URI for cross-platform compatibility.
```tsx
import { SpotifyClientAuthProvider } from "@/lib/spotify-auth/spotify-client-provider";
import { makeRedirectUri } from "expo-auth-session";
const redirectUri = makeRedirectUri({ scheme: "exspotify" });
export default function App() {
return (
);
}
```
--------------------------------
### Playlist Information UI Component (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
A React component designed to display comprehensive playlist details, including album art, track listings, and owner information. It features an animated header and presents track details such as song name, artist, and album artwork.
```tsx
import Playlist from "@/components/playlist-info";
function PlaylistRoute() {
const data = {
name: "Today's Top Hits",
description: "The hottest tracks right now",
images: [{ url: "https://...", height: 640, width: 640 }],
owner: {
display_name: "Spotify",
external_urls: { spotify: "https://..." },
},
tracks: {
total: 50,
items: [
{
track: {
id: "abc123",
name: "Song Name",
artists: [{ name: "Artist Name" }],
album: { images: [{ url: "https://..." }] },
external_urls: { spotify: "https://..." },
},
},
],
},
};
const user = {
display_name: "Spotify",
images: [{ url: "https://..." }],
followers: { total: 50000000 },
};
return ;
}
```
--------------------------------
### Render Search Results Component (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Renders search results for artists, songs, and albums in a sectioned list format. It requires data to be fetched and processed before rendering. The component can also display a loading skeleton while data is being fetched.
```tsx
import SearchResults from "@/components/search-results";
import { SearchResultsSkeleton } from "@/components/search-results";
function SearchRoute() {
const data = {
artists: {
items: [
{
id: "artist1",
name: "Drake",
images: [{ url: "https://..." }],
followers: { total: 72000000 },
external_urls: { spotify: "https://..." },
},
],
},
tracks: {
items: [
{
id: "track1",
name: "One Dance",
artists: [{ name: "Drake" }],
album: { images: [{ url: "https://..." }] },
external_urls: { spotify: "https://..." },
},
],
},
albums: {
items: [
{
id: "album1",
name: "Views",
artists: [{ name: "Drake" }],
images: [{ url: "https://..." }],
external_urls: { spotify: "https://..." },
},
],
},
};
// Show loading skeleton while fetching
if (isLoading) {
return ;
}
return ;
}
```
--------------------------------
### Direct Spotify API Calls with Auth Injection (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Provides functions for making authenticated requests to any Spotify endpoint, automatically injecting the necessary authorization tokens. It supports fetching typed JSON data and custom fetch requests, with built-in error handling for invalid endpoints or requests.
```tsx
import { fetchSpotifyDataAsync, fetchWithAuth } from "@/components/spotify/spotify-server-api";
// Fetch typed JSON data
const userData = await fetchSpotifyDataAsync("/v1/me");
// {
// display_name: "John Doe",
// email: "john@example.com",
// followers: { total: 234 },
// images: [{ url: "https://...", height: 300, width: 300 }]
// }
// Custom fetch with auth headers
const response = await fetchWithAuth("/v1/me/top/artists?limit=10", {
method: "GET",
});
const artists = await response.json();
// Errors are automatically thrown
try {
await fetchSpotifyDataAsync("/v1/invalid-endpoint");
} catch (error) {
console.error(error.message); // "The requested resource was not found"
console.error(error.statusCode); // 404
}
```
--------------------------------
### Server-Side Access Token Management with Auto-Refresh (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Injects authentication into server functions, automatically refreshing access tokens when they expire. This utility ensures that background server processes always have a valid token for API interactions. It returns the action results and the latest token if a refresh occurred.
```tsx
import { withAccessToken } from "@/components/spotify/spotify-server-api";
// Define a server action
async function myServerAction(userId: string) {
"use server";
// Auth is automatically available via getServerAuth()
return await fetchSpotifyDataAsync(`/v1/users/${userId}`);
}
// Wrap with auto-auth on client
const { results, latestToken } = await withAccessToken(
{
action: myServerAction,
accessToken: currentAuth,
},
"user123"
);
// If token was refreshed, latestToken will contain new credentials
if (latestToken) {
console.log("Token refreshed:", latestToken.access_token);
// Store updated token on client
}
```
--------------------------------
### Exchange Spotify Auth Code for Access Token (TypeScript)
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Securely exchanges an authorization code for an access token on the server using the client secret. This is crucial for secure OAuth 2.0 flows, preventing exposure of sensitive credentials. It returns access and refresh tokens along with their expiry information.
```tsx
import { exchangeAuthCodeAsync, refreshTokenAsync } from "@/lib/spotify-auth/auth-server-actions";
// Exchange auth code after OAuth redirect
const tokens = await exchangeAuthCodeAsync({
code: "AQD8s7f6sd8f7sd...",
redirectUri: "exspotify://redirect",
});
// tokens contains:
// {
// access_token: "BQC4js8d...",
// token_type: "Bearer",
// expires_in: 1734441234567, // Unix timestamp in ms
// refresh_token: "AQB9s8d...",
// scope: "user-read-email playlist-read-private"
// }
// Refresh expired token
const refreshed = await refreshTokenAsync(tokens.refresh_token);
```
--------------------------------
### Use Spotify Auth Hook for Authentication State
Source: https://context7.com/evanbacon/expo-router-spotify/llms.txt
Provides a hook to access Spotify authentication state and methods within any component. It allows checking authentication status, manually refreshing tokens, and logging out.
```tsx
import { useSpotifyAuth } from "@/lib/spotify-auth";
function ProfileButton() {
const {
accessToken,
auth,
clearAccessToken,
getFreshAccessToken,
useSpotifyAuthRequest
} = useSpotifyAuth();
// Check if user is authenticated
if (!accessToken) {
return ;
}
// Manually refresh token if needed
const handleRefresh = async () => {
try {
const freshAuth = await getFreshAccessToken();
console.log("Token expires:", freshAuth.expires_in);
} catch (error) {
console.error("Refresh failed:", error);
}
};
// Logout
const handleLogout = () => {
clearAccessToken();
};
return (
);
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.