Project Overview:
Create a fully functional, multi-page Next.js MVP application called 'StreamBoost' (formerly Twitch Roulette). The primary goal is to help Twitch viewers discover smaller, less-browsed live streamers and for these streamers to gain visibility and new viewers. The application will address the problem of discoverability for emerging streamers on Twitch by providing advanced filtering, curated discovery ('Roulette' mode), and insightful statistics. The core value proposition is empowering viewers with personalized content discovery and providing streamers with a platform to grow their audience organically.
Tech Stack:
- Framework: Next.js (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- UI Components: shadcn/ui (for clean, accessible components)
- ORM: Drizzle ORM (PostgreSQL compatibility)
- Database: PostgreSQL (e.g., via Vercel Postgres, Supabase, or a self-hosted instance)
- Authentication: NextAuth.js (with Twitch OAuth integration)
- State Management: React Context API / Zustand (for global state if needed, otherwise component state)
- Data Fetching: Server Actions & Route Handlers in Next.js App Router
- Deployment: Vercel (recommended for seamless Next.js deployment)
- Other Libraries: `zod` for validation, `react-hot-toast` for notifications, `lucide-react` for icons.
Database Schema (PostgreSQL with Drizzle ORM):
```sql
-- Users table for authentication and profile information
CREATE TABLE users (
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255) UNIQUE,
emailVerified TIMESTAMP(3),
image TEXT, -- URL of profile picture
twitch_username VARCHAR(255) UNIQUE, -- Twitch username
twitch_id VARCHAR(255) UNIQUE, -- Twitch user ID for OAuth
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Table to store information about followed streamers (from Twitch API)
CREATE TABLE followed_streamers (
user_id VARCHAR(255) REFERENCES users(id) ON DELETE CASCADE,
streamer_twitch_id VARCHAR(255),
streamer_login VARCHAR(255), -- Twitch username
streamer_display_name VARCHAR(255),
followed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, streamer_twitch_id)
);
-- Table for user preferences/filters (optional for MVP, can be managed client-side initially)
-- CREATE TABLE user_preferences (
-- user_id VARCHAR(255) PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
-- preferred_games TEXT[],
-- preferred_languages TEXT[],
-- max_viewers INTEGER
-- );
-- Potential future table for saved/favorited streams or channels
-- CREATE TABLE favorite_channels (
-- user_id VARCHAR(255) REFERENCES users(id) ON DELETE CASCADE,
-- channel_id VARCHAR(255),
-- saved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- PRIMARY KEY (user_id, channel_id)
-- );
```
Core Features & User Flow:
1. **Authentication (Twitch OAuth):**
* **User Flow:** User clicks 'Sign In with Twitch' button. Redirected to Twitch OAuth page. User authorizes the app. Redirected back to the app's dashboard. User's Twitch info (ID, username, display name, profile picture) is fetched and stored/updated in the `users` table. If the user is new, create an entry; if existing, update. `NextAuth.js` will manage the session.
* **Edge Cases:** Twitch API token refresh, error handling during OAuth, user denies access.
2. **Streamer Discovery - 'Roulette' Mode:**
* **User Flow:** User navigates to the 'Roulette' page. Clicks 'Find a Streamer'. The backend fetches a list of currently live Twitch streamers, filters out those with a high viewer count (e.g., > 500 viewers, configurable). From the remaining list, a random streamer is selected and displayed. The display includes their profile picture, username, current game, title, and viewer count. A button allows the user to 'View Stream' (linking to their Twitch channel) and 'Find Another'.
* **Backend Logic:** Utilize Twitch API's 'Get Streams' endpoint with `first=100` (or more) and filter parameters. Implement server-side logic to apply the viewer count threshold and select randomly. Cache results briefly to avoid excessive API calls.
* **Edge Cases:** No streamers found matching criteria (display 'No streams found, try again later'), API errors, empty viewer counts.
3. **Streamer Discovery - Advanced Filters:**
* **User Flow:** User navigates to the 'Discover' page. A form with filters is presented: Game (dropdown populated by Twitch API), Language (dropdown), Max Viewers (slider/input), Tags (multi-select). User applies filters. The backend queries the Twitch API using these parameters. Results are displayed as a list/grid of cards, each showing streamer info (pic, name, game, title, viewers). Users can click a card to view stream details or go to the streamer's profile.
* **Backend Logic:** Construct Twitch API request dynamically based on selected filters. Handle pagination if many results are returned. `zod` can be used to validate filter inputs.
* **Edge Cases:** No results found, invalid filter combinations, API rate limits.
4. **Streamer Statistics:**
* **User Flow:** On the 'Discover' page or 'Roulette' results, clicking a streamer card navigates to a dedicated 'Streamer Profile' page. This page displays detailed, real-time (or near real-time) statistics fetched from the Twitch API: current viewers, peak viewers (if available), followers, uptime, stream title, current game, VODs (if available). For logged-in users, a 'Follow/Unfollow' button (interacting with `followed_streamers` table and Twitch API) and a 'Save to Favorites' button are present.
* **Backend Logic:** Fetch stream data and user data endpoints from Twitch API. Store follow/favorite status in the local database.
* **Edge Cases:** Streamer is offline (display offline status and last known stats), API unavailable, follower counts not updating instantly.
5. **Follow/Favorite Management (Logged-in Users):**
* **User Flow:** Logged-in users can click 'Follow' on a streamer's profile page. This adds an entry to their `followed_streamers` table in the database and potentially triggers a follow action via Twitch API (if the API allows this for third-party apps, otherwise it's just for internal tracking). A 'My Followed Streams' page lists all followed streamers, showing their current online status and basic info. Similarly, users can 'Favorite' channels for quick access.
* **Backend Logic:** Use Server Actions to handle database inserts/deletes for follows/favorites. API calls to Twitch for follow status updates if applicable.
* **Edge Cases:** User is not logged in, follow action fails, unfollow action.
API & Data Fetching:
- **Twitch API:** Primary data source. Endpoints like `Get Streams`, `Get Users`, `Search Categories`. Use `fetch` with appropriate headers (Client-ID, Authorization). Implement caching strategies (e.g., using `next-வதில்` or Redis) to respect Twitch API rate limits.
- **Next.js Route Handlers (API Routes):** For backend logic like handling OAuth callbacks, processing filter requests before hitting Twitch API, and managing follow/favorite actions (Server Actions are preferred for mutations).
- **Server Actions:** For mutations (creating/updating/deleting data) directly from components, especially for authentication and follow/favorite management.
- **Data Flow:** Client components request data. For server-rendered data (like streamer lists), use `fetch` within Server Components or Route Handlers. For client-side mutations (e.g., toggling favorite), use Server Actions triggered by button clicks. Data will be passed as props from Server Components to Client Components or fetched client-side using `useEffect` if necessary.
Component Breakdown (Next.js App Router Structure):
- `/app/layout.tsx`: Root layout (includes `<html>`, `<body>`, global providers, header/footer).
- `/app/page.tsx`: Landing Page (brief intro, call to action for sign-in).
- `/app/dashboard/page.tsx`: (Client Component) User dashboard after login. Shows 'My Followed Streams', maybe featured Roulette stream.
- `/app/auth/signin/page.tsx`: Sign-in page with Twitch OAuth button.
- `/app/discover/page.tsx`: (Client Component) Main discovery page with filter form and results grid.
- `/app/stream/[username]/page.tsx`: (Server Component) Dynamic route for individual streamer profile page, fetching data server-side.
- `/app/roulette/page.tsx`: (Client Component) The 'Roulette' feature page.
- `/components/ui/` (shadcn/ui components):
* `Button`
* `Input`
* `Card` (for streamer display)
* `Sheet` or `Dialog` (for filter options)
* `Avatar`
* `Skeleton` (for loading states)
* `NavigationMenu` or `Tabs` (for main navigation)
* `Switch` / `Slider`
- `/components/auth/`: Auth related components (e.g., `SignInButton`).
- `/components/stream/`: Components specific to stream display (e.g., `StreamCard`, `StreamStats`, `FilterForm`).
- `/components/layout/`: Header, Footer, Sidebar components.
- `/lib/`: Utility functions, Twitch API client, database client (Drizzle).
- `/hooks/`: Custom React hooks.
- `/styles/globals.css`: Tailwind CSS base styles.
UI/UX Design & Visual Identity:
- **Style:** Modern, Clean, slightly Futuristic. Focus on clarity and ease of navigation.
- **Color Palette:**
* Primary: Deep Purple (`#6D28D9`)
* Secondary: Vibrant Blue (`#2563EB`)
* Accent/Highlight: Teal/Cyan (`#14B8A6`)
* Background: Dark Gray (`#1F2937`)
* Text: Light Gray (`#D1D5DB`), White (`#FFFFFF`)
- **Typography:** Sans-serif font like Inter or Manrope for readability. Clear hierarchy using font weights and sizes.
- **Layout:** Use a consistent grid system (e.g., 12-column). Sidebar for navigation (on larger screens) or off-canvas menu (on mobile). Main content area should be spacious. Use cards for displaying streamer information.
- **Responsiveness:** Mobile-first approach. Ensure usability on all screen sizes. Grids should adapt, navigation should be mobile-friendly.
- **Visual Elements:** Subtle gradients on buttons or headers. Use `lucide-react` icons for clarity. Streamer cards should prominently feature profile pictures and live status indicators.
Animations:
- **Page Transitions:** Subtle fade-in/out using Next.js' `AnimatePresence` (if using Framer Motion) or CSS transitions.
- **Hover Effects:** Slight scale-up or shadow change on interactive elements like buttons and streamer cards.
- **Loading States:** Use `Skeleton` components from shadcn/ui while data is being fetched. Add subtle shimmer effects to skeletons.
- **Button Feedback:** Micro-interactions on click (slight press-down effect).
- **Tag/Filter Interactions:** Smooth transitions when adding/removing tags or changing filter values.
Sample/Mock Data (for `StreamCard` component):
1. **Live Streamer 1:**
* `displayName`: "PixelPioneer"
* `login`: "pixelpioneer_"
* `profileImageURL`: "https://picsum.photos/seed/pixel/40/40"
* `gameName`: "Indie Game Dev"
* `title`: "Building my dream RPG! Come hang out!"
* `viewerCount`: 42
* `isLive`: true
2. **Live Streamer 2:**
* `displayName`: "SynthWaveSurfer"
* `login`: "synthwavesurfer_"
* `profileImageURL`: "https://picsum.photos/seed/synth/40/40"
* `gameName`: "Music Production"
* `title`: "Live Lo-fi Beats Session 🎶"
* `viewerCount`: 15
* `isLive`: true
3. **Live Streamer 3 (Just Started):**
* `displayName`: "CodeCrafterKai"
* `login`: "codecrafterkai_"
* `profileImageURL`: "https://picsum.photos/seed/code/40/40"
* `gameName`: "Software Development"
* `title`: "Morning stream - refactoring a Node.js API"
* `viewerCount`: 8
* `isLive`: true
4. **Offline Streamer:**
* `displayName`: "ArtisticAlice"
* `login`: "artistic_alice_"
* `profileImageURL`: "https://picsum.photos/seed/art/40/40"
* `gameName`: "Art"
* `title`: "(Offline)"
* `viewerCount`: 0
* `isLive`: false
* `lastOnline`: "2 days ago"
5. **High Viewer Count Streamer (to be filtered out by default):**
* `displayName`: "GamerGodX"
* `login`: "gamergodx_"
* `profileImageURL`: "https://picsum.photos/seed/gamer/40/40"
* `gameName`: "Valorant"
* `title`: "Road to Grandmaster - HUGE GIVEAWAY!"
* `viewerCount`: 5500
* `isLive`: true
6. **Streamer with Specific Tag:**
* `displayName`: "CozyGamerChloe"
* `login`: "cozygamerchloe_"
* `profileImageURL`: "https://picsum.photos/seed/cozy/40/40"
* `gameName`: "Stardew Valley"
* `title`: "Farming and chilling ☕"
* `viewerCount`: 25
* `isLive`: true
* `tags`: ["cozy", "farming", "chill"]
7. **Non-English Streamer:**
* `displayName`: "ElProGamerES"
* `login`: "elprogamer_es_"
* `profileImageURL`: "https://picsum.photos/seed/es/40/40"
* `gameName`: "League of Legends"
* `title`: "Jugando Ranked - ¡Vamos a subir!"
* `viewerCount`: 18
* `isLive`: true
* `language`: "es"
Turkish Translations:
- **App Title:** StreamBoost (Görünmez Akış Bulucu)
- **Sign In:** Oturum Aç
- **Sign In with Twitch:** Twitch ile Oturum Aç
- **Discover:** Keşfet
- **Roulette:** Rulet
- **My Followed Streams:** Takip Ettiklerim
- **Streamer:** Yayıncı
- **Game:** Oyun
- **Viewers:** İzleyici
- **Live:** Yayında
- **Offline:** Yayında Değil
- **Follow:** Takip Et
- **Unfollow:** Takibi Bırak
- **Favorite:** Favoriye Ekle
- **Remove Favorite:** Favorilerden Çıkar
- **Filters:** Filtreler
- **Apply Filters:** Filtreleri Uygula
- **Clear Filters:** Filtreleri Temizle
- **No streams found:** Hiç yayın bulunamadı.
- **Try again later:** Lütfen daha sonra tekrar deneyin.
- **Find Another Streamer:** Başka Yayıncı Bul
- **Stream Title:** Yayın Başlığı
- **Stats:** İstatistikler
- **Followers:** Takipçiler
- **Uptime:** Yayın Süresi
- **Loading...:** Yükleniyor...
- **Error:** Bir hata oluştu.
- **Something went wrong:** Bir şeyler ters gitti.
- **Search by Game, Language, or Tags:** Oyun, Dil veya Etiketlere Göre Ara
- **Max Viewers:** Maksimum İzleyici
- **Settings:** Ayarlar
- **Profile:** Profil
- **Sign Out:** Oturumu Kapat
- **Welcome back, [Username]!:** Tekrar hoş geldin, [Kullanıcı Adı]!
- **Explore new talents:** Yeni yetenekleri keşfedin.
- **Boost your stream visibility:** Akışınızın görünürlüğünü artırın.