Skip to content

Tech stack

Built for performance & creativity

A modern full stack Next.js portfolio with OAuth 2.0, AWS cloud integration, and custom audio playback architecture.

The stack

What it runs on

Languages & framework

  • Next.js 16React framework + API routes
  • React 19Client UI + playback context
  • TypeScriptStrict mode, app to API
  • Tailwind CSSDesign tokens + utilities
  • Motion (Framer)Menus, sheets and panels

Cloud & backend

  • AWS S3Cloud storage for audio files
  • Spotify API + OAuth 2.0Web Playback SDK + token refresh
  • VercelServerless deployment & hosting

State & data

  • React Context APIGlobal playback state & queue management
  • In-memory cachingS3 URL caching with 55min expiration
  • Cookie-based sessionsSpotify OAuth token storage

Key features

What makes it tick

  1. 01

    Spotify OAuth 2.0 integration

    Full OAuth flow with cookie-based session management, automatic token refresh, and server-side token caching. Supports both client credentials and user authorization flows.

  2. 02

    AWS S3 pre-signed URLs

    Dynamic audio delivery with 55-minute URL expiration and intelligent caching. Server-side signing prevents credential exposure while maintaining performance.

  3. 03

    Dual audio sources

    Unified playback interface supporting both HTML5 Audio API for beats and Spotify Web Playback SDK for streaming. Context-aware controls adapt to the active source.

  4. 04

    Persistent audio playback

    Audio continues playing seamlessly across page navigation using React Context and root layout mounting. Smart state management prevents interruptions during route changes.

Backend

API routes

Audio delivery

  • GET/api/beatsReturns all beats with metadata
  • GET/api/beats/playlistsReturns the beat packs
  • POST/api/beats/signedUrlGenerates a signed URL for a specific beat

Spotify OAuth

  • GET/api/spotify/loginInitiates Spotify OAuth 2.0 authorization flow
  • GET/api/spotify/callbackHandles OAuth callback and exchanges code for tokens
  • GET/api/spotify/tokenRetrieves or refreshes Spotify access token
  • POST/api/spotify/logoutClears the Spotify session cookies

Spotify data

  • GET/api/spotify/playlistsFetches user playlists from Spotify API
  • GET/api/spotify/playlist/[id]Fetches one playlist with its tracks
  • GET/api/spotify/stats/topTracksFetches user’s most played tracks
  • GET/api/spotify/stats/topArtistsFetches user’s top artists

Under the hood

Signed audio, cached

providers/PlayBarProvider.tsx
// Reuse a signed S3 URL until it's about to expire
const cached = urlCache.get(track.id)
const now = Date.now()
let audioUrl: string

if (cached && cached.expiresAt > now) {
  audioUrl = cached.url
} else {
  const url = await getBeatSignedUrl(track.id)
  const expiresAt = now + 55 * 60 * 1000
  audioUrl = url
  setUrlCache(prev => new Map(prev).set(track.id, { url, expiresAt }))
}

setSelectedTrack({ ...track, audioUrl })
setIsPlaying(true)

Performance

Fast by default

First load
<2s
Bundle size
~220KB
Lighthouse
95+

Security & best practices

Locked down

Token & session security

  • Spotify tokens stored in HttpOnly, Secure cookies and cleared on logout
  • Refresh flow runs server-side only; client never sees secrets
  • Short-lived access tokens; refresh token retained for 30 days

Signed URL access control

  • S3 pre-signed URLs generated per request with 55-minute expiry
  • Bucket kept private; audio is never publicly exposed
  • URLs cached with TTL to avoid stale or reused links

API design & validation

  • Beat/playlist IDs and required fields are validated before calling Spotify/S3
  • All secrets stay server-side; Spotify client secret never ships to the client
  • API routes handle OAuth exchanges and signing; UI consumes safe endpoints

Resilience & error handling

  • Graceful fallbacks between Spotify SDK and HTML5 Audio playback
  • Ad-block detection with user-facing guidance instead of silent failure
  • Consistent try/catch with user-friendly error states in the UI

Check out the code

View the full source code, architecture decisions, and implementation details. Clean codebase, full TypeScript, production-ready.

View on GitHub