Skip to content

Feature/pbi 72 playlist export#82

Merged
vas2000-emu merged 53 commits into
mainfrom
feature/pbi-72-playlist-export
Dec 1, 2025
Merged

Feature/pbi 72 playlist export#82
vas2000-emu merged 53 commits into
mainfrom
feature/pbi-72-playlist-export

Conversation

@eabdelkh

@eabdelkh eabdelkh commented Nov 17, 2025

Copy link
Copy Markdown
Contributor

Feature: YouTube Playlist Export for Groups & Communities (PBI-72)

🎯 Overview

This PR implements a comprehensive YouTube playlist export feature that allows users to export their curated playlists from both Groups and Communities directly to their YouTube account. The implementation follows a modular, extensible architecture designed for reliability and reusability.

✨ Key Features

1. Unified Export API (/api/export/youtube)

  • Dual-source support: Handles both group and community playlist exports via a single endpoint
  • Backward compatibility: Legacy groupId parameter still works for existing integrations
  • Intelligent song fetching: Queries playlist_songs for groups, curated_songs (approved only) for communities
  • Robust error handling: Comprehensive validation with clear error messages

2. Reusable Export Button Component (ExportPlaylistButton.jsx)

  • Prop-driven configuration: Accepts sourceType, sourceId, playlistId, defaultName
  • Built-in dialog UI: Custom playlist naming with confirmation flow
  • Loading states: Visual feedback during export process
  • Toast notifications: Success/failure feedback with playlist link

3. Rate Limiting & Retry Logic

  • 1-second throttle between YouTube API requests to prevent rate limiting
  • Automatic retry (1 attempt with 2s delay) for transient errors (409, 503, 429)
  • Sequential processing: for...of loop ensures deterministic order
  • Philosophy: Reliability > Speed — better to take 30s and succeed 100% than 5s with failures

🏗️ Technical Implementation

API Changes

Request Body (New Format):

{
  "sourceType": "group" | "community",
  "sourceId": "uuid",
  "playlistId": "uuid" | "all",
  "customName": "Optional playlist name"
}

Response:

{
  "message": "YouTube playlist export completed",
  "sourceType": "community",
  "sourceId": "uuid",
  "youtubePlaylistId": "PLxxxxx",
  "youtubePlaylistUrl": "https://www.youtube.com/playlist?list=PLxxxxx",
  "playlistTitle": "[Vybe Export] Community Name",
  "totalSongs": 16,
  "songsAdded": 16,
  "songsFailed": 0,
  "results": { "successful": [...], "failed": [...] }
}

Component Architecture

ExportPlaylistButton
├── Props: sourceType, sourceId, playlistId, defaultName, disabled, className
├── State: showExportDialog, customPlaylistName, isExporting
├── Mutation: useMutation → /api/export/youtube
└── UI: Button + Dialog with input + confirmation

Database Queries

Source Type Table Filter Order
group playlist_songs playlist_id position ASC
community curated_songs community_id, status='approved' created_at ASC

🐛 Bug Fixes

PKCE Authentication Fix

  • Issue: invalid request: both auth code and code verifier should be non-empty
  • Root Cause: Next.js 15 changed cookies() to be async; our route handlers weren't awaiting it
  • Fix: Updated lib/supabase/route.js to properly await cookies(), fixed all route handlers using supabaseRoute()

YouTube Rate Limiting Fix

  • Issue: Random 409 SERVICE_UNAVAILABLE / ABORTED errors (14/16 songs succeeding)
  • Root Cause: 100ms delay was too aggressive for YouTube's write rate limits
  • Fix: Implemented 1s throttle + retry logic with exponential backoff

📁 Files Changed

New Files

  • apps/web/components/ExportPlaylistButton.jsx — Reusable export button component

Modified Files

  • apps/web/app/api/export/youtube/route.js — Refactored for dual-source support + retry logic
  • apps/web/app/groups/[id]/page.jsx — Refactored to use ExportPlaylistButton
  • apps/web/components/HomePage.jsx — Added export button to Community Detail Dialog
  • apps/web/lib/supabase/route.js — Fixed async cookies() for Next.js 15
  • apps/web/app/auth/callback/route.js — Fixed PKCE token exchange
  • apps/web/app/sign-out/route.js — Fixed async supabaseRoute() call
  • apps/web/app/api/history/route.js — Fixed async supabaseRoute() call
  • memory-bank/architecture.md — Documented Communities feature structure

Merged from playlist-order-ai

  • AI Smart Sort feature for group playlists
  • Settings page enhancements (privacy, notifications)
  • Various UI improvements

✅ Testing

Manual Test Cases Validated

  1. ✅ Export group playlist to YouTube (existing functionality preserved)
  2. ✅ Export community playlist to YouTube (new functionality)
  3. ✅ Custom playlist naming works correctly
  4. ✅ Only approved songs from communities are exported
  5. ✅ Rate limiting prevents API errors (16/16 songs succeed)
  6. ✅ Retry logic handles transient failures
  7. ✅ PKCE authentication flow works after fix
  8. ✅ Export button only shows when YouTube is connected

API Tests (Browser Console)

// Test Community Export
fetch('/api/export/youtube', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    sourceType: 'community',
    sourceId: '<community-uuid>'
  })
}).then(r => r.json()).then(console.log);

🔮 Future Enhancements

  • Spotify playlist export (same component, different API)
  • Progress indicator during long exports
  • Batch export multiple communities
  • Export history/tracking in database

vas2000-emu and others added 18 commits September 13, 2025 23:13
- Remove Privacy and Notifications tabs from settings navigation
- Delete privacy and notifications page files
- Improve mobile responsiveness with better padding and layouts
- Enhance SettingsNav mobile menu (slides from right, better touch targets)
- Add notification bell icon to Navbar (desktop and mobile)
- Create NotificationBell and NotificationDropdown components
- Create useNotifications hook with placeholder data
- Optimize form inputs for mobile (better touch handling, responsive text)
- Update conflict resolution handlers to remove privacy/notifications cases
- Add old-pbi/ and pbi-77/ to .gitignore

All settings now focus on essential features: Profile and Account only.
- Add 'Export to YouTube' button to group playlist view
  - Button only visible for users with YouTube/Google accounts
  - Works for both individual and 'All Playlists' views
  - Uses Youtube icon from lucide-react

- Create /api/export/youtube POST endpoint
  - Authenticates user via Supabase session
  - Validates playlistId and groupId parameters
  - Fetches songs from playlist_songs table (ordered by position/created_at)
  - Creates YouTube playlist using YouTube Data API v3
  - Returns playlist URL and metadata

- Fix middleware to allow API routes to handle their own auth
  - API routes can now return proper JSON error responses (401, etc.)
  - Prevents unwanted redirects to sign-in page for API endpoints

Note: Requires Supabase configuration:
- Google OAuth scope: youtube.force-ssl
- RLS policy fix for youtube_tokens table
See pbi-72/SUPABASE-YOUTUBE-SETUP-REQUIRED.md for setup guide
@vercel

vercel Bot commented Nov 17, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
vybe Ready Ready Preview Comment Nov 30, 2025 7:11pm

- Added youtube.force-ssl scope to Google OAuth sign-in
- This enables playlist creation/management permissions
- Users will see a new consent screen requesting YouTube permissions
…& add

- Implemented search-and-add loop for songs using YouTube Search API
- Added sequential processing with 100ms rate limiting between requests
- Implemented robust error handling for search failures and quota limits
- Added detailed result tracking (successful/failed songs with reasons)
- Returns comprehensive response with song counts and error details
- Gracefully handles quota exceeded errors (testing pending quota reset)

Testing Notes:
- Feature implementation complete and validated in logs
- Hit YouTube API quota limit during testing (resets midnight PT)
- Will validate full success with smaller playlist tomorrow

Related Files:
- apps/web/app/api/export/youtube/route.js
- memory-bank/progress.md
- memory-bank/architecture.md
- memory-bank/code-review-notes.md
HuTaoEMU and others added 2 commits November 19, 2025 14:04
- Connected frontend UI to API using React Query useMutation
- Added loading states and user feedback with toast notifications
- Removed temporary console.log debugging statements (kept console.error for error handling)
- Updated progress.md to mark feature as COMPLETE
- Rewrote code-review-notes.md into cohesive presentation script
- Updated architecture.md with frontend integration details
vas2000-emu and others added 26 commits November 24, 2025 00:35
…iting

- Add sleep() helper and addVideoToPlaylistWithRetry() function
- Implement 1-second throttle between YouTube API requests
- Add retry logic (1 retry with 2s delay) for 409/503/429 errors
- Change loop to for...of for cleaner sequential processing
- Reliability > Speed: exports now complete 100% vs random failures

Fixes random SERVICE_UNAVAILABLE/ABORTED errors during playlist export
@vas2000-emu vas2000-emu merged commit b54f6db into main Dec 1, 2025
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants