From bb8ed2deec45748a66baf09be02144d63acf246a Mon Sep 17 00:00:00 2001 From: mbrucedogs Date: Sun, 20 Jul 2025 12:58:57 -0500 Subject: [PATCH] Signed-off-by: mbrucedogs --- docs/PRD-backup.md | 2627 ++++++++++++++++ docs/PRD.md | 2795 +++-------------- docs/README.md | 53 +- docs/platforms/web/PRD-web.md | 759 +++++ docs/platforms/web/README.md | 132 + .../web/design}/00-web-layout.JPG | Bin .../web => platforms/web/design}/01-Login.png | Bin .../web => platforms/web/design}/02-menu.jpeg | Bin .../web/design}/02-queue-delete.png | Bin .../web/design}/02-queue-drag.png | Bin .../web/design}/02-queue-sorting.png | Bin .../web => platforms/web/design}/02-queue.png | Bin .../web/design}/02a-menu.jpeg | Bin .../web => platforms/web/design}/02b-menu.png | Bin .../web/design}/02c-menu.jpeg | Bin .../03-menu current page and non-admin.png | Bin .../web/design}/03-menu playing (admin).png | Bin .../web => platforms/web/design}/03-menu.png | Bin .../web/design}/04-search typing .png | Bin .../web/design}/04-search-song info.png | Bin .../web/design}/04-search.png | Bin .../web/design}/05-singers add.png | Bin .../web/design}/05-singers.png | Bin .../web/design}/06-artists (not admin).png | Bin .../web/design}/06-artists .png | Bin .../web/design}/06-artists search.png | Bin .../web/design}/06-artists songs.png | Bin .../web/design}/07-favorites.png | Bin .../web/design}/08-history.png | Bin .../design}/09- song lists songs expand.png | Bin .../web/design}/09-song lists - songs.png | Bin .../web/design}/09-songs list.png | Bin .../web/design}/10-Settings.png | Bin .../web/design}/11-top 100.png | Bin .../web/design}/12-favorite lists.png | Bin .../web/design}/12-favorites .png | Bin 36 files changed, 3998 insertions(+), 2368 deletions(-) create mode 100644 docs/PRD-backup.md create mode 100644 docs/platforms/web/PRD-web.md create mode 100644 docs/platforms/web/README.md rename docs/{design/web => platforms/web/design}/00-web-layout.JPG (100%) rename docs/{design/web => platforms/web/design}/01-Login.png (100%) rename docs/{design/web => platforms/web/design}/02-menu.jpeg (100%) rename docs/{design/web => platforms/web/design}/02-queue-delete.png (100%) rename docs/{design/web => platforms/web/design}/02-queue-drag.png (100%) rename docs/{design/web => platforms/web/design}/02-queue-sorting.png (100%) rename docs/{design/web => platforms/web/design}/02-queue.png (100%) rename docs/{design/web => platforms/web/design}/02a-menu.jpeg (100%) rename docs/{design/web => platforms/web/design}/02b-menu.png (100%) rename docs/{design/web => platforms/web/design}/02c-menu.jpeg (100%) rename docs/{design/web => platforms/web/design}/03-menu current page and non-admin.png (100%) rename docs/{design/web => platforms/web/design}/03-menu playing (admin).png (100%) rename docs/{design/web => platforms/web/design}/03-menu.png (100%) rename docs/{design/web => platforms/web/design}/04-search typing .png (100%) rename docs/{design/web => platforms/web/design}/04-search-song info.png (100%) rename docs/{design/web => platforms/web/design}/04-search.png (100%) rename docs/{design/web => platforms/web/design}/05-singers add.png (100%) rename docs/{design/web => platforms/web/design}/05-singers.png (100%) rename docs/{design/web => platforms/web/design}/06-artists (not admin).png (100%) rename docs/{design/web => platforms/web/design}/06-artists .png (100%) rename docs/{design/web => platforms/web/design}/06-artists search.png (100%) rename docs/{design/web => platforms/web/design}/06-artists songs.png (100%) rename docs/{design/web => platforms/web/design}/07-favorites.png (100%) rename docs/{design/web => platforms/web/design}/08-history.png (100%) rename docs/{design/web => platforms/web/design}/09- song lists songs expand.png (100%) rename docs/{design/web => platforms/web/design}/09-song lists - songs.png (100%) rename docs/{design/web => platforms/web/design}/09-songs list.png (100%) rename docs/{design/web => platforms/web/design}/10-Settings.png (100%) rename docs/{design/web => platforms/web/design}/11-top 100.png (100%) rename docs/{design/web => platforms/web/design}/12-favorite lists.png (100%) rename docs/{design/web => platforms/web/design}/12-favorites .png (100%) diff --git a/docs/PRD-backup.md b/docs/PRD-backup.md new file mode 100644 index 0000000..4c5661e --- /dev/null +++ b/docs/PRD-backup.md @@ -0,0 +1,2627 @@ +# 🎀 Karaoke App β€” Product Requirements Document (PRD) + +--- + +## πŸš€ How to Use This PRD + +**For AI Implementation:** When you read this PRD, please: +1. **Read the entire document completely** - it contains comprehensive technical specifications +2. **Ask the 7 implementation questions** from Section 29 to determine platform/framework choices +3. **Follow the implementation checklist** from Section 29 for the complete build process +4. **Preserve all business logic** while adapting UI to the chosen framework +5. **Use the exact specifications** for data flows, service APIs, and error handling + +**For Human Developers:** This PRD contains complete technical specifications including data flows, state management, service APIs, component architecture, error handling, and performance optimizations. It's designed for 100% accuracy when building from scratch. + +--- + +> **Note:** This PRD is structured for platform-agnostic use. Each feature is described with platform-independent requirements, followed by a 'Web Implementation Details' section for web-specific behaviors. For future platforms (iOS, Android, etc.), add corresponding implementation details under each feature. This ensures the PRD can be used as the single source of truth for any platform. +> +> **Toolset/Framework Sections:** Each platform implementation includes explicit toolset/framework choices with rationale. This preserves the "why" behind current choices while enabling seamless migration to new technologies. When migrating, replace the toolset section while keeping the core requirements intact. + +--- + +## 1. Purpose + +This document defines the functional, technical, and UX requirements for the Karaoke App, designed for **in-home party use**. The app leverages **Firebase Realtime Database** for real-time synchronization, with all business logic and validation handled **client-side**. + +--- + +## 2. Scope & Business Objectives + +- Deliver a single-session karaoke experience where users connect to a controller and manage/search songs. +- Use Firebase for real-time multi-user sync of queues, history, and playback state. +- Prioritize fast performance, reusable modular architecture, and clear business logic separation. +- Enable adding songs from multiple entry points (search, history, top played, favorites, new songs, artists, song lists). +- Ensure graceful handling of Firebase sync issues using retry patterns and partial node updates. +- True Separation of Concerns - UI components only handle presentation +- Reusable Business Logic - Hooks can be used across components +- Testable Code - Business logic separated from UI +- Maintainable - Changes to logic don't affect UI +- Performance - Memoized selectors and optimized hooks +- Type Safety - Full TypeScript coverage throughout +- The codebase needs to follow the Single Responsibility Principle perfectly - each file has one clear purpose! + +--- + +## 2.5. Toolset & Framework Choices + +### **Current Web Implementation Toolset:** + +#### **Core Framework: React 18 + TypeScript** +- **Why:** Component-based architecture, strong ecosystem, excellent TypeScript support +- **Migration Note:** Can be replaced with any component-based framework (Vue, Svelte, etc.) + +#### **State Management: Redux Toolkit** +- **Why:** Centralized state management, predictable state updates, excellent dev tools +- **Key Requirements:** Must support real-time sync, optimistic updates, and complex state relationships +- **Migration Note:** Can be replaced with Zustand, Jotai, Valtio, or any state management solution that supports: + - Centralized state + - Real-time updates + - Optimistic updates + - Complex selectors + +#### **UI Framework: Ionic React** +- **Why:** Mobile-first design, native feel, excellent accessibility, built-in components +- **Key Requirements:** Must support responsive design, touch interactions, and accessibility +- **Migration Note:** Can be replaced with any UI framework that provides: + - Responsive components + - Touch-optimized interactions + - Accessibility support + - Modal/dialog components + - List components with infinite scroll + +#### **Styling: Tailwind CSS** +- **Why:** Utility-first CSS, rapid development, consistent design system +- **Migration Note:** Can be replaced with any CSS solution (CSS Modules, Styled Components, etc.) + +#### **Build Tool: Vite** +- **Why:** Fast development server, optimized builds, excellent TypeScript support +- **Migration Note:** Can be replaced with any modern build tool (Webpack, Parcel, etc.) + +#### **Backend: Firebase Realtime Database** +- **Why:** Real-time sync, simple setup, excellent for collaborative apps +- **Key Requirements:** Must support real-time listeners, offline capabilities, and complex queries +- **Migration Note:** Can be replaced with any real-time database (Supabase, AWS AppSync, etc.) + +#### **Cloud Functions: Firebase Functions** +- **Why:** Serverless, integrates with Firebase, automatic scaling +- **Migration Note:** Can be replaced with any serverless platform (AWS Lambda, Vercel Functions, etc.) + +### **Architecture Patterns:** + +#### **Service Layer Pattern** +- **Why:** Separation of concerns, testable business logic, reusable across components +- **Implementation:** All Firebase operations abstracted into service modules +- **Migration Note:** Must maintain service layer pattern regardless of backend choice + +#### **Hook Pattern** +- **Why:** Reusable business logic, separation of UI and logic, testable +- **Implementation:** Custom hooks for each feature (useQueue, useSearch, etc.) +- **Migration Note:** Can be replaced with any pattern that separates business logic from UI + +#### **Component Composition** +- **Why:** Reusable components, clear separation of concerns, maintainable +- **Implementation:** Common components (SongItem, ActionButton, etc.) used across features +- **Migration Note:** Must maintain component composition regardless of framework choice + +--- + +## 3. User Roles & Permissions + +**Requirements (Platform-Agnostic):** +- Two roles: Host/Admin and Singer/User. +- Only admins can reorder or delete queue items, control playback, and manage singers. +- Admin access is a privileged mode (see platform details for how it's triggered). +- First queue item cannot be deleted while playing (only when stopped/paused). +- Singers are automatically added to the singers list when they join. + +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#authentication` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#authentication` (future) +- **Android:** See `platforms/android/PRD-android.md#authentication` (future) + +--- + +## 4. Feature Overview + +### Authentication & Session Management +**Requirements (Platform-Agnostic):** +- Login requires both Party ID and singer name. +- Party ID is validated against the backend before login is allowed. +- Authentication state is managed in the app state and lost on app reload (unless platform supports persistence). + +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#authentication` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#authentication` (future) +- **Android:** See `platforms/android/PRD-android.md#authentication` (future) + +### Search +**Requirements (Platform-Agnostic):** +- Local search on preloaded song catalog. +- Instant search results as user types. +- Paginated/infinite scroll results. +- Context actions for each song (add to queue, favorite, etc). + +**Web Implementation Details:** +- Uses Ionic InfiniteScrollList for pagination. + +### Queue Management +**Requirements (Platform-Agnostic):** +- Shared queue synchronized across all clients. +- Queue items must always use sequential numerical keys (0, 1, 2, ...). +- The system must automatically fix any inconsistencies in order values or keys on every update. +- Queue reordering must be atomic; when two items are swapped, both order values are updated in a single operation. +- Only admins can reorder or delete queue items, and only when playback is stopped or paused. +- Duplicate songs are prevented in the queue by checking the song’s `path`. +- Each queue item shows which singer added it. + +**Web Implementation Details:** +- Queue reordering and deletion are exposed via UI controls only visible to admins. +- UI uses drag handles and swipe actions (Ionic components) for reordering and deletion. + +### Favorites +**Requirements (Platform-Agnostic):** +- Shared favorites list synchronized across all clients. +- Anyone can add/remove favorites. +- Duplicate prevention by song `path`. +- Paginated/infinite scroll display. + +**Web Implementation Details:** +- Uses Ionic InfiniteScrollList for pagination. + +### New Songs +**Requirements (Platform-Agnostic):** +- Shows recently added songs from the `newSongs` node. +- Real-time updates and infinite scroll. + +**Web Implementation Details:** +- Uses Ionic InfiniteScrollList for pagination. + +### Artists +**Requirements (Platform-Agnostic):** +- Browse songs by artist with search functionality. +- Modal view for all songs by an artist. +- Song count per artist. +- Paginated/infinite scroll artist list. + +**Web Implementation Details:** +- Uses Ionic modals and InfiniteScrollList. + +### Song Lists +**Requirements (Platform-Agnostic):** +- Predefined song lists with themes/collections. +- Song matching to catalog. +- Expandable view for available versions. +- Modal interface for viewing list contents. +- Shows which songs are available in the catalog. + +**Web Implementation Details:** +- Uses Ionic modals and InfiniteScrollList. + +### History Tracking +**Requirements (Platform-Agnostic):** +- Songs automatically added to history when played. +- Shows when each song was last played. +- Append-only, shared across all clients. +- Paginated/infinite scroll display. + +**Web Implementation Details:** +- Uses Ionic InfiniteScrollList for pagination. + +### Top Played +**Requirements (Platform-Agnostic):** +- Popular songs generated by backend based on history. +- Shows play count for each song. +- Real-time updates and infinite scroll. + +**Web Implementation Details:** +- Uses Ionic InfiniteScrollList for pagination. + +### Singer Management +**Requirements (Platform-Agnostic):** +- Only admins can add or remove singers. +- Singer names must be unique and non-empty. +- Singers are automatically added to the list when they join. +- All users can view the current singers list. +- Tracks when each singer last joined. + +**Web Implementation Details:** +- Singer management UI is available only to admins via the settings page. + +### Playback Control +**Requirements (Platform-Agnostic):** +- Only admins can control playback (play, pause, stop). +- Play button is disabled if the queue is empty. +- UI state (play/pause/stop) must reflect the current player state. + +**Web Implementation Details:** +- Player controls are only rendered for admins. +- State-based UI: play/pause/stop buttons shown/hidden based on current state. + +### Error Handling & Sync +**Requirements (Platform-Agnostic):** +- Graceful handling of sync failures with retry patterns. +- Full controller object loaded on initial connection. +- Incremental updates target specific child nodes. +- Real-time connection status monitoring. +- Graceful handling of missing or empty data. + +**Web Implementation Details:** +- Uses web-specific toast notifications and error boundaries. + +### Disabled Songs +**Requirements (Platform-Agnostic):** +- Admins can disable or enable songs. +- Disabled songs are stored using a hash of the song path for key safety. + +**Web Implementation Details:** +- Disabled songs are managed via a modal dialog with search and filter capabilities. + +### Settings +**Requirements (Platform-Agnostic):** +- Only admins can change player settings (autoadvance, userpick). + +**Web Implementation Details:** +- Debug logging is a web-only feature, toggled via the settings page. + +### Navigation +**Requirements (Platform-Agnostic):** +- Admin-only pages (e.g., settings) must be hidden from non-admin users. + +**Web Implementation Details:** +- Navigation adapts based on admin status; settings page is only visible to admins. + +### UI/UX & Platform-Specifics +**Requirements (Platform-Agnostic):** +- All business logic, validation, and permissions must be enforced at the application level, not just in the UI. + +**Web Implementation Details:** +- The web implementation uses Ionic React and Tailwind CSS for UI. +- Features like infinite scroll, swipe actions, modals, and toasts are implemented using Ionic components. +- Session persistence, URL parameter handling, and debug logging are web-specific. + +--- + +## 5. Data Models + +Data models are defined externally in: +> [`types.ts`](./types.ts) + +This file contains TypeScript interfaces describing: +- `Song` β€” Core song data with artist, title, path, and metadata +- `QueueItem` β€” Queue entries with order, singer, and song data +- `Singer` β€” User information with name and last login +- `SongList` β€” Predefined song collections with metadata +- `SongListSong` β€” Individual songs within a song list +- `TopPlayed` β€” Popular songs with play count +- `Controller` β€” Main object containing all app data +- `PlayerState` β€” Playback status enum (Playing, Paused, Stopped) +- `Authentication` β€” User session data with admin status +- `Settings` β€” Player settings (autoadvance, userpick) + +**Key Data Relationships:** +- Songs are identified by their `path` field for duplicate prevention +- Queue items have sequential `order` values for proper ordering +- All data is stored as Firebase records with string keys +- History tracks play dates and counts for each song + +--- + +## 6. Firebase Realtime Database Structure + +Defined externally in: +> [`firebase_schema.json`](./firebase_schema.json) + +**Complete Structure:** +```json +controllers: { + [controllerName]: { + favorites: Record, + history: Record, + topPlayed: Record, + newSongs: Record, + disabledSongs: Record, + player: { + queue: Record, + settings: Settings, + singers: Record, + state: Player + }, + songList: Record, + songs: Record + } +} +``` + +**Data Flow:** +- **Initial Sync:** Loads the complete `controller` object on connection +- **Real-time Updates:** Subscribes to specific nodes for incremental updates +- **Key Management:** Uses sequential numerical keys for queue items +- **Auto-initialization:** Creates empty controller structure if none exists + +**Empty Controller Structure:** +```json +{ + "favorites": {}, + "history": {}, + "topPlayed": {}, + "newSongs": {}, + "disabledSongs": {}, + "player": { + "queue": {}, + "settings": { + "autoadvance": false, + "userpick": false + }, + "singers": {}, + "state": { + "state": "stopped" + } + }, + "songList": {}, + "songs": {} +} +``` + +**Key Generation Rules:** +- **Queue Items:** Sequential numerical keys (0, 1, 2, ...) +- **Top Played:** `sanitizedArtist_sanitizedTitle` (lowercase, trimmed, invalid chars replaced with `_`) +- **Disabled Songs:** Hash of song path (simple character-based hash) +- **Singers:** Firebase push IDs (auto-generated) + +**Character Sanitization for Top Played Keys:** +- Replace invalid Firebase characters `[.#$/[\]]` with `_` +- Convert to lowercase and trim whitespace +- Format: `${sanitizedArtist}_${sanitizedTitle}` + +--- + +## 7. UI/UX Behavior + +**Requirements (Platform-Agnostic):** +- Responsive design that works on all device sizes. +- Support for light/dark mode themes. +- Modern, clean, intuitive interface with consistent styling. +- Accessibility support (keyboard navigation, screen readers). +- Tab-based navigation with clear active states. +- Consistent empty state views for all lists. +- Loading states with spinner animations. +- Toast notifications for success/error feedback. +- Consistent button styling with variants. +- Reusable song display with context-aware actions. +- Infinite scroll for automatic loading of additional content. +- Context-specific behavior for different screens (search, queue, history, etc.). +- Admin-specific UI elements (playback controls, queue reorder, singer management). + +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#uiux-behavior` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#uiux-behavior` (future) +- **Android:** See `platforms/android/PRD-android.md#uiux-behavior` (future) + +--- + +## 8. UI Rules & Constraints + +**Requirements (Platform-Agnostic):** + +### **Queue Management Rules:** +- Only admin users can reorder queue items. +- First queue item cannot be deleted while playing (only when stopped/paused). +- Reorder constraints: items not at top/bottom can move up/down. +- Queue items must maintain sequential order (1, 2, 3, etc.). +- Automatic cleanup of inconsistent order values on queue initialization. +- Queue items use sequential numerical keys (0, 1, 2, etc.). + +### **Playback Control Rules:** +- Player controls only visible to admin users. +- Play button is disabled when queue is empty. +- State-based controls: play/pause/stop buttons shown/hidden based on current state. +- Current player state must be clearly displayed. + +### **Search Rules:** +- Search only activates after 2+ characters. +- Debounce delay before search execution. +- Search scope includes both song title and artist fields (case-insensitive). +- Empty search shows all songs. +- Search resets to page 1 when search term changes. + +### **Pagination & Infinite Scroll Rules:** +- 20 items loaded per page. +- Load more logic only shows when there are more items than currently displayed. +- Triggers load more when user scrolls to bottom 10% of list. +- Each feature maintains its own page state independently. +- All lists must use pagination to prevent UI blocking. +- Progressive loading of items as user scrolls. +- Loading state management with spinner when no items are loaded yet. +- Page reset on search term changes. +- Memory optimization for smooth scrolling. +- Error handling for load more failures. +- Accessibility support for infinite scroll. + +### **Toast Notification Rules:** +- Duration settings: Success/Info 3 seconds, Error 5 seconds. +- Auto-dismiss after duration. +- Manual dismiss option. +- Multiple toasts can be displayed simultaneously. + +### **Authentication Rules:** +- Admin access is a privileged mode (see platform details for implementation). +- Session persistence behavior varies by platform. +- Both Party ID and singer name required for login. + +### **Data Display Rules:** +- Loading states with spinner when data count is 0. +- Empty states when data exists but filtered results are empty. +- Debug information display for development. +- User attribution indicators for current user's queue items. +- Availability status for unmatched song list items. + +### **Action Button Rules:** +- Context-based actions for different screens. +- Permission-based visibility based on user role. +- State-based disabling of buttons. +- Confirmation feedback for all actions. + +### **Modal & Overlay Rules:** +- Modal views for artist songs and song lists. +- Proper backdrop and close actions. + +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#ui-rules` for React/Ionic implementation details +- **iOS:** See `platforms/ios/PRD-ios.md#ui-rules` (future) +- **Android:** See `platforms/android/PRD-android.md#ui-rules` (future) + +### **Error Handling Rules:** +- **Error Boundaries:** React error boundaries catch component-level errors +- **Graceful Degradation:** App continues to work with cached data during connection issues +- **User Feedback:** Clear error messages with recovery options +- **Retry Logic:** Automatic retry for failed Firebase operations +- **Fallback Values:** Default values provided for missing or corrupted data + +### **Performance Rules:** +- **Memoization:** Expensive operations memoized with `useMemo` and `useCallback` +- **Debouncing:** Search input debounced to prevent excessive API calls +- **Incremental Loading:** Large datasets loaded in chunks via infinite scroll +- **Optimistic Updates:** UI updates immediately, with rollback on error +- **Connection Monitoring:** Real-time connection status tracking + +### **Data Validation Rules:** +- **Type Safety:** All data validated against TypeScript interfaces +- **Required Fields:** Critical fields (controller name, singer name) validated before operations +- **Duplicate Prevention:** Songs identified by `path` field for duplicate checking +- **Order Validation:** Queue order automatically fixed if inconsistencies detected +- **Key Cleanup:** Inconsistent Firebase keys automatically migrated to sequential format + +### **Feature Flag Rules:** +- **Configurable Features:** Features can be enabled/disabled via constants: + - `ENABLE_SEARCH: true` + - `ENABLE_QUEUE_REORDER: true` + - `ENABLE_FAVORITES: true` + - `ENABLE_HISTORY: true` + - `ENABLE_TOP_PLAYED: true` + - `ENABLE_ADMIN_CONTROLS: true` + +### **Constants & Limits:** +- **Queue Limits:** Maximum 100 items (`MAX_ITEMS: 100`) +- **History Limits:** Maximum 50 items (`MAX_ITEMS: 50`) +- **Top Played Limits:** Maximum 20 items (`MAX_ITEMS: 20`) +- **Search Limits:** Minimum 2 characters, 300ms debounce +- **Toast Limits:** Success/Info 3s, Error 5s duration + +--- + +## 9. Codebase Organization & File Structure + +### **Folder Structure & Purpose:** + +| Folder | Purpose | Key Files | Import Pattern | +|--------|---------|-----------|----------------| +| `/components/common` | Shared UI components | `ActionButton.tsx`, `EmptyState.tsx`, `SongItem.tsx`, `InfiniteScrollList.tsx` | `import { ComponentName } from '../components/common'` | +| `/components/Auth` | Authentication components | `AuthInitializer.tsx`, `LoginPrompt.tsx` | `import { AuthInitializer } from '../components/Auth'` | +| `/components/Layout` | Layout and navigation | `Layout.tsx`, `Navigation.tsx` | `import Layout from '../components/Layout/Layout'` | +| `/features` | Feature-specific components | `Search.tsx`, `Queue.tsx`, `History.tsx`, `Artists.tsx`, `SongLists.tsx` | `import { Search, Queue } from '../features'` | +| `/hooks` | Business logic hooks | `useQueue.ts`, `useSearch.ts`, `useSongOperations.ts` | `import { useQueue, useSearch } from '../hooks'` | +| `/redux` | State management | `controllerSlice.ts`, `authSlice.ts`, `selectors.ts` | `import { useAppDispatch, selectQueue } from '../redux'` | +| `/firebase` | Firebase services | `services.ts`, `FirebaseProvider.tsx` | `import { queueService } from '../firebase/services'` | +| `/types` | TypeScript definitions | `index.ts` (extends docs/types.ts) | `import type { Song, QueueItem } from '../types'` | +| `/utils` | Utility functions | `dataProcessing.ts` | `import { filterSongs } from '../utils/dataProcessing'` | +| `/constants` | App constants | `index.ts` | `import { UI_CONSTANTS } from '../constants'` | + +### **Index File Pattern:** +Each folder uses an `index.ts` file to export all public APIs: + +```typescript +// src/hooks/index.ts +export { useFirebaseSync } from './useFirebaseSync'; +export { useSongOperations } from './useSongOperations'; +export { useToast } from './useToast'; +export { useSearch } from './useSearch'; +export { useQueue } from './useQueue'; +// ... all other hooks + +// src/components/common/index.ts +export { default as ActionButton } from './ActionButton'; +export { default as EmptyState } from './EmptyState'; +export { default as Toast } from './Toast'; +// ... all other components + +// src/features/index.ts +export { default as Search } from './Search/Search'; +export { default as Queue } from './Queue/Queue'; +export { default as History } from './History/History'; +// ... all other features +``` + +### **Import Organization Patterns:** + +#### **1. Redux Imports:** +```typescript +// Always import from the main redux index +import { useAppDispatch, useAppSelector } from '../redux'; +import { selectQueue, selectSongs } from '../redux'; +import { setController, updateQueue } from '../redux'; + +// Never import directly from slice files +// ❌ import { selectQueue } from '../redux/controllerSlice'; +// βœ… import { selectQueue } from '../redux'; +``` + +#### **2. Hook Imports:** +```typescript +// Import hooks from the main hooks index +import { useQueue, useSearch, useSongOperations } from '../hooks'; + +// Import specific hooks when needed +import { useToast } from '../hooks/useToast'; +``` + +#### **3. Component Imports:** +```typescript +// Import from feature index for feature components +import { Search, Queue, History } from '../features'; + +// Import from common index for shared components +import { ActionButton, EmptyState, SongItem } from '../components/common'; + +// Import layout components directly +import Layout from '../components/Layout/Layout'; +``` + +#### **4. Type Imports:** +```typescript +// Always use type imports for TypeScript interfaces +import type { Song, QueueItem } from '../types'; + +// Import specific types when needed +import type { RootState } from '../types'; +``` + +#### **5. Service Imports:** +```typescript +// Import Firebase services directly +import { queueService, favoritesService } from '../firebase/services'; + +// Import Firebase configuration +import { database } from '../firebase/config'; +``` + +#### **6. Utility Imports:** +```typescript +// Import utility functions directly +import { filterSongs, objectToArray } from '../utils/dataProcessing'; +``` + +#### **7. Constant Imports:** +```typescript +// Import constants from the main constants index +import { UI_CONSTANTS, FEATURES } from '../constants'; +``` + +### **File Organization Principles:** + +#### **Single Responsibility Principle:** +- **Each file has one clear purpose** +- **Hooks handle business logic only** +- **Components handle UI rendering only** +- **Services handle external API calls only** +- **Types define data structures only** + +#### **Separation of Concerns:** +- **UI Components:** Only handle presentation and user interaction +- **Business Logic:** Extracted into custom hooks +- **State Management:** Centralized in Redux slices +- **Data Access:** Abstracted in Firebase services +- **Type Definitions:** Centralized in types folder + +#### **Dependency Direction:** +``` +Components β†’ Hooks β†’ Redux β†’ Services β†’ Firebase + ↓ ↓ ↓ ↓ ↓ + Types ← Types ← Types ← Types ← Types +``` + +### **Redux Architecture Pattern:** + +#### **Slice Organization:** +```typescript +// src/redux/controllerSlice.ts +export const controllerSlice = createSlice({ + name: 'controller', + initialState, + reducers: { + setController: (state, action) => { /* ... */ }, + updateQueue: (state, action) => { /* ... */ }, + // ... other reducers + }, +}); + +// Export actions and selectors +export const { setController, updateQueue } = controllerSlice.actions; +export const selectController = (state: RootState) => state.controller.data; +``` + +#### **Selector Pattern:** +```typescript +// src/redux/selectors.ts +export const selectSongsArray = createSelector( + [selectSongs], + (songs) => sortSongsByArtistAndTitle(objectToArray(songs)) +); + +export const selectQueueWithUserInfo = createSelector( + [selectQueue, selectCurrentSinger], + (queue, currentSinger) => addUserInfoToQueue(queue, currentSinger) +); +``` + +#### **Hook Integration:** +```typescript +// src/hooks/useQueue.ts +export const useQueue = () => { + const queueItems = useAppSelector(selectQueueWithUserInfo); + const dispatch = useAppDispatch(); + + const handleRemoveFromQueue = useCallback(async (queueItemKey: string) => { + try { + await queueService.removeFromQueue(controllerName, queueItemKey); + } catch (error) { + showError('Failed to remove song from queue'); + } + }, [controllerName, showError]); + + return { queueItems, handleRemoveFromQueue }; +}; +``` + +### **Hook Architecture Pattern:** + +#### **Hook Composition:** +```typescript +// Base operations hook +export const useSongOperations = () => { + // Common song operations (add to queue, toggle favorite) +}; + +// Feature-specific hooks compose base hooks +export const useQueue = () => { + const { removeFromQueue, toggleFavorite } = useSongOperations(); + const { showSuccess, showError } = useToast(); + // Queue-specific logic +}; + +export const useSearch = () => { + const { addToQueue, toggleFavorite } = useSongOperations(); + const { showSuccess, showError } = useToast(); + // Search-specific logic +}; +``` + +#### **Hook Dependencies:** +```typescript +// Hooks depend on Redux state and services +export const useQueue = () => { + const queueItems = useAppSelector(selectQueueWithUserInfo); + const { removeFromQueue } = useSongOperations(); + const { showError } = useToast(); + + // Hook logic here +}; +``` + +### **Component Architecture Pattern:** + +#### **Component Structure:** +```typescript +// Feature components are simple and focused +export const Queue = () => { + const { queueItems, handleRemoveFromQueue } = useQueue(); + + return ( +
+ +
+ ); +}; +``` + +#### **Component Dependencies:** +```typescript +// Components only depend on hooks and UI components +import { useQueue } from '../hooks'; +import { InfiniteScrollList, SongItem } from '../components/common'; +import type { QueueItem } from '../types'; +``` + +### **Type Organization Pattern:** + +#### **Type Definitions:** +```typescript +// src/types/index.ts +export interface Song { + artist: string; + title: string; + path: string; + favorite?: boolean; +} + +export interface QueueItem { + key?: string; + order: number; + singer: Singer; + song: Song; +} + +export interface RootState { + controller: ControllerState; + auth: AuthState; +} +``` + +#### **Type Usage:** +```typescript +// Always use type imports +import type { Song, QueueItem } from '../types'; + +// Use in function parameters and return types +const addToQueue = async (song: Song): Promise => { + // Implementation +}; +``` + +### **Service Architecture Pattern:** + +#### **Service Organization:** +```typescript +// src/firebase/services.ts +export const queueService = { + addToQueue: async (controllerName: string, queueItem: Omit) => { + // Implementation + }, + removeFromQueue: async (controllerName: string, queueItemKey: string) => { + // Implementation + }, + subscribeToQueue: (controllerName: string, callback: (data: Record) => void) => { + // Implementation + }, +}; +``` + +#### **Service Usage:** +```typescript +// Import services directly +import { queueService, favoritesService } from '../firebase/services'; + +// Use in hooks +const handleAddToQueue = useCallback(async (song: Song) => { + await queueService.addToQueue(controllerName, queueItem); +}, [controllerName]); +``` + +### **Constants Organization Pattern:** + +#### **Constants Structure:** +```typescript +// src/constants/index.ts +export const UI_CONSTANTS = { + TOAST_DURATION: { + SUCCESS: 3000, + ERROR: 5000, + INFO: 3000, + }, + SEARCH: { + DEBOUNCE_DELAY: 300, + MIN_SEARCH_LENGTH: 2, + }, +} as const; + +export const FEATURES = { + ENABLE_SEARCH: true, + ENABLE_QUEUE_REORDER: true, +} as const; +``` + +#### **Constants Usage:** +```typescript +// Import constants from main index +import { UI_CONSTANTS, FEATURES } from '../constants'; + +// Use in components and hooks +const debounceDelay = UI_CONSTANTS.SEARCH.DEBOUNCE_DELAY; +``` + +### **Import Order Convention:** +```typescript +// 1. React imports +import { useState, useCallback, useEffect } from 'react'; + +// 2. Third-party library imports +import { useAppSelector, useAppDispatch } from '../redux'; + +// 3. Internal imports (alphabetical by folder) +import { useSongOperations } from '../hooks'; +import { queueService } from '../firebase/services'; +import { UI_CONSTANTS } from '../constants'; +import { filterSongs } from '../utils/dataProcessing'; + +// 4. Type imports +import type { Song, QueueItem } from '../types'; +``` + +### **File Naming Conventions:** +- **Components:** PascalCase (e.g., `SongItem.tsx`, `InfiniteScrollList.tsx`) +- **Hooks:** camelCase with `use` prefix (e.g., `useQueue.ts`, `useSongOperations.ts`) +- **Services:** camelCase with `Service` suffix (e.g., `queueService`, `favoritesService`) +- **Types:** PascalCase (e.g., `Song`, `QueueItem`, `Controller`) +- **Constants:** UPPER_SNAKE_CASE (e.g., `UI_CONSTANTS`, `FEATURES`) +- **Utilities:** camelCase (e.g., `dataProcessing.ts`, `filterSongs`) + +### **Critical Import Rules:** +- **Never import directly from slice files** - always use the main redux index +- **Always use type imports** for TypeScript interfaces +- **Import from index files** for organized modules (hooks, components, features) +- **Import services directly** from their service files +- **Import utilities directly** from their utility files +- **Import constants** from the main constants index + +--- + +## πŸ”Ÿ Cloud Function Design β€” Top Played + +### **Automatic Top Played Calculation:** +- **Trigger:** Firebase Cloud Function triggered when song added to `history` +- **Action:** Recalculates entire top played list based on history aggregation +- **Benefits:** Non-blocking updates, real-time popularity tracking +- **Data Structure:** Stores artist, title, and count for each popular song + +### **Key Generation Logic:** +- **Format:** `sanitizedArtist_sanitizedTitle` +- **Sanitization:** Replace invalid Firebase characters `[.#$/[\]]` with `_` +- **Processing:** Convert to lowercase and trim whitespace +- **Example:** "AC/DC" + "Back in Black" β†’ "ac_dc_back_in_black" + +### **Aggregation Algorithm:** +- **Group By:** Artist + Title combination (case-insensitive) +- **Count Logic:** Sum all `count` values for same artist/title +- **Sorting:** Sort by count descending, limit to top 100 +- **Data Structure:** Convert array back to object format for Firebase + +### **Manual Recalculation Function:** +- **Function Name:** `recalculateTopPlayed` +- **Trigger:** Manual HTTP callable function +- **Purpose:** Data migration, initial setup, or data repair +- **Input:** `{ controllerName: string }` +- **Output:** Success/failure status with message + +### **Error Handling:** +- **Validation:** Require controllerName parameter +- **Empty Data:** Return empty topPlayed if no history exists +- **Logging:** Console logs for debugging and monitoring + +--- + +## 11. External Reference Files + +| File | Purpose | +|------|---------| +| [`types.ts`](./types.ts) | Core TypeScript interfaces for data models | +| [`firebase_schema.json`](./firebase_schema.json) | Firebase Realtime Database structure reference | +| [`design/`](./design/) | UI/UX mockups and design specifications | + +--- + +## 12. Data Access Model & Validation + +> **Client-Controlled Access Model** + +This app does **not** use Firebase Realtime Database Security Rules. +All permissions, validation, and business logic are enforced in the client application. + +### **Enforced Client-Side:** +- βœ… **Admin-only permissions** for queue reorder, playback control, and singer management +- βœ… **Duplicate song prevention** enforced before adding to queue/favorites +- βœ… **Singer auto-addition** when users join the session +- βœ… **Data validation** against TypeScript interfaces before Firebase writes +- βœ… **Queue order management** with sequential numbering and cleanup +- βœ… **First item protection** preventing deletion during playback + +### **Business Logic Validation:** +- **Queue Operations:** Order validation, duplicate prevention, singer attribution +- **Authentication:** Admin mode detection, session management +- **Data Integrity:** Type checking, required field validation +- **State Management:** Redux state consistency, error handling + +**Assumed Environment:** +- The app is used in trusted, in-home scenarios with controlled participants +- Open Firebase access is considered acceptable for this use case +- All users are trusted participants in the karaoke session + +--- + +## 13. Performance & Optimization + +### **State Management:** +- **Redux Toolkit:** Efficient state management with immutable updates +- **Memoized Selectors:** Optimized data access with `createSelector` +- **Incremental Loading:** Pagination and infinite scroll for large datasets +- **Real-time Sync:** Efficient Firebase subscriptions with cleanup + +### **UI Performance:** +- **React.memo:** Component memoization to prevent unnecessary re-renders +- **useCallback/useMemo:** Hook optimization for expensive operations +- **Virtual Scrolling:** Efficient rendering of large lists (implementation pending) +- **Lazy Loading:** Code splitting for better initial load times + +### **Data Optimization:** +- **Efficient Queries:** Optimized Firebase queries with specific node subscriptions +- **Caching Strategy:** Redux state caching with timestamp-based invalidation +- **Batch Operations:** Grouped Firebase updates for better performance +- **Connection Management:** Proper cleanup of Firebase listeners + +### **List Performance & UI Blocking Prevention:** +- **Mandatory Pagination:** All lists MUST use pagination to prevent UI blocking +- **Progressive Rendering:** Only render visible items plus small buffer (20 items per page) +- **Intersection Observer:** Efficient scroll detection without performance impact +- **Memory Management:** Automatic cleanup of observers and event listeners +- **Virtual Scrolling:** Future implementation for very large datasets (1000+ items) +- **Debounced Operations:** Search and filter operations debounced to prevent excessive re-renders +- **Memoized Selectors:** Redux selectors memoized to prevent unnecessary re-computations +- **Optimistic Updates:** UI updates immediately with rollback on error +- **Lazy Loading:** Images and heavy content loaded only when needed +- **Render Optimization:** React.memo and useCallback for expensive operations +- **Bundle Splitting:** Code splitting for better initial load times + +--- + +## 14. Error Handling & Resilience + +### **Firebase Connection:** +- **Connection Monitoring:** Real-time connection status tracking +- **Retry Logic:** Automatic retry for failed operations +- **Graceful Degradation:** App continues to work with cached data +- **Error Boundaries:** React error boundaries for component-level error handling + +### **Data Validation:** +- **Type Safety:** TypeScript compilation-time error prevention +- **Runtime Validation:** Data structure validation before Firebase writes +- **Fallback Values:** Default values for missing or corrupted data +- **User Feedback:** Clear error messages and recovery options + +### **State Recovery:** +- **Session Persistence:** Authentication state recovery +- **Data Rehydration:** Redux state restoration from Firebase +- **Conflict Resolution:** Handling concurrent user modifications +- **Data Consistency:** Automatic cleanup of inconsistent data structures + +--- + +## 15. Testing Strategy + +### **Unit Testing:** +- **Hook Testing:** Business logic hooks with isolated testing +- **Selector Testing:** Redux selector validation +- **Utility Testing:** Pure function testing for data processing +- **Type Testing:** TypeScript interface validation + +### **Integration Testing:** +- **Firebase Integration:** Real-time sync testing +- **Redux Integration:** State management flow testing +- **Component Integration:** UI component interaction testing +- **API Testing:** Firebase service layer testing + +### **E2E Testing:** +- **User Flow Testing:** Complete user journey validation +- **Multi-user Testing:** Concurrent user interaction testing +- **Performance Testing:** Load testing for large datasets +- **Cross-browser Testing:** Browser compatibility validation + +--- + +## 16. Deployment & Environment + +### **Build Configuration:** +- **Vite:** Fast build tool with hot module replacement +- **TypeScript:** Strict type checking and compilation +- **ESLint:** Code quality and consistency enforcement +- **Tailwind CSS:** Utility-first CSS framework + +### **Environment Variables:** +- **Firebase Config:** Database connection configuration +- **Controller Name:** Default controller for development +- **Feature Flags:** Environment-specific feature toggles + +### **Deployment Targets:** +- **Development:** Local development with hot reload +- **Staging:** Pre-production testing environment +- **Production:** Live karaoke app deployment + +--- + +## 17. Firebase Implementation Patterns + +### **Key Management & Data Structure:** +- **Sequential Numerical Keys:** Queue items use sequential numerical keys (0, 1, 2, etc.) instead of Firebase push IDs +- **Key Migration:** Automatic cleanup of inconsistent keys (migrate push ID keys to sequential numerical keys) +- **Order Validation:** Queue items maintain sequential order (1, 2, 3, etc.) with automatic cleanup +- **Controller Structure:** Complete controller object loaded on initial connection with empty initialization if not exists + +### **Queue Key Migration Logic:** +- **Cleanup Function:** `cleanupQueueKeys()` migrates push ID keys to sequential numerical keys +- **Key Validation:** Regex pattern `/^\d+$/` to identify numerical keys +- **Migration Strategy:** Find push ID keys, assign sequential keys, update Firebase atomically + +### **Queue Order Calculation:** +- **Order Logic:** `Math.max(...queueItems.map(item => item.order || 0)) + 1` +- **Fallback Handling:** Use `|| 0` for missing order values +- **Auto-Fix:** Check for inconsistencies on every queue update and fix automatically + +### **Disabled Songs Implementation:** +- **Hash Function:** Simple character-based hash for Firebase-safe keys +- **Hash Algorithm:** `((hash << 5) - hash) + charCodeAt(i)` converted to base36 +- **Timeout Handling:** 10-second timeout for all disabled song operations +- **Validation:** Required fields (controller name, song path, artist, title) +- **Integration:** Filter disabled songs from all search results + +### **Search Algorithm Details:** +- **Multi-word Logic:** AND logic for multiple terms, OR logic for single term +- **Term Processing:** Split on whitespace, filter empty terms +- **Matching:** Case-insensitive includes check on title and artist +- **Disabled Filtering:** Exclude disabled songs from all results +- **Loading States:** Don't show results while disabled songs are loading + +### **Authentication Validation:** +- **Controller Existence Check:** Verify controller exists in Firebase before login +- **Error Messages:** "Invalid Party Id. Please check your Party Id and try again." +- **Field Validation:** Both Party ID and singer name required and trimmed + +### **Singer Name Validation:** +- **Case-insensitive Comparison:** `.toLowerCase()` for duplicate checking +- **Trim Validation:** Remove whitespace from singer names +- **Unique Constraint:** Prevent duplicate singer names (case-insensitive) + +### **Error Handling & Timeouts:** +- **Timeout Values:** 10-second timeout for Firebase operations +- **Specific Error Messages:** "Singer already exists", "Controller not found", etc. +- **Error Recovery:** Handle specific error types with appropriate user feedback + +### **Redux Store Configuration:** +- **Serializable Check:** Disabled for development (`serializableCheck: false`) +- **Immutable Check:** Ignored paths for large data objects +- **Middleware Configuration:** Specific Redux Toolkit settings for performance + +### **Firebase Services Architecture:** +- **Service Layer Pattern:** All Firebase operations abstracted into service modules: + - `controllerService` - Controller CRUD operations + - `queueService` - Queue management with key cleanup + - `playerService` - Player state management + - `historyService` - History operations + - `favoritesService` - Favorites management +- **Subscription Pattern:** Each service provides subscribe/unsubscribe functions for real-time updates +- **Error Handling:** Service functions include try-catch blocks with console logging + +### **Real-time Sync Implementation:** +- **FirebaseProvider Pattern:** Centralized sync management with connection status tracking +- **Full Controller Load:** Initial load of complete controller object on authentication +- **Empty Controller Initialization:** Creates empty controller structure if none exists +- **Connection Status:** Real-time tracking of `isConnected` and `syncStatus` states +- **Cleanup Management:** Proper cleanup of Firebase listeners on unmount + +### **Queue Management Patterns:** +- **Sequential Key Generation:** Next key calculated as `Math.max(existingKeys) + 1` +- **Key Cleanup Function:** `cleanupQueueKeys()` migrates push ID keys to sequential numerical keys +- **Order Calculation:** Next order calculated as `Math.max(existingOrders) + 1` +- **Order Fixing:** Automatic queue order validation and repair in `useQueue` hook +- **Swap Operations:** Queue reordering uses Promise.all for atomic updates + +### **Data Validation & Type Safety:** +- **TypeScript Interfaces:** All data validated against TypeScript interfaces before Firebase writes +- **Required Field Validation:** Critical fields (controller name, singer name) validated before operations +- **Fallback Values:** Default values provided for missing or corrupted data +- **Type Assertions:** Safe type casting with existence checks + +### **Error Handling Patterns:** +- **Service-Level Error Handling:** Each service function includes try-catch with console logging +- **Hook-Level Error Handling:** Custom hooks include error handling with toast notifications +- **Graceful Degradation:** App continues to work with cached data during connection issues +- **Error Boundaries:** React error boundaries for component-level error handling +- **Connection Monitoring:** Real-time connection status with error state management + +### **Performance Optimization Patterns:** +- **Efficient Queries:** Specific node subscriptions instead of full controller subscriptions +- **Listener Cleanup:** Proper cleanup of Firebase listeners to prevent memory leaks +- **Batch Operations:** Grouped Firebase updates using `update()` for better performance +- **Memoized Selectors:** Redux selectors memoized to prevent unnecessary re-computations +- **Incremental Loading:** Large datasets loaded in chunks via infinite scroll + +### **Authentication Integration:** +- **Controller-Based Sessions:** Users connect to specific controller sessions +- **Admin Parameter Handling:** Admin access via URL parameter with automatic cleanup +- **Session Persistence:** Authentication state managed in Redux (lost on page reload) +- **Auto-Initialization:** Empty controller created if none exists for new sessions + +### **Constants & Configuration:** +- **Environment Variables:** Firebase config loaded from environment variables with fallbacks +- **Feature Flags:** Configurable features via constants (ENABLE_SEARCH, ENABLE_QUEUE_REORDER, etc.) +- **UI Constants:** Centralized constants for toast durations, search delays, item limits +- **Error Messages:** Centralized error message constants for consistency + +### **Critical Implementation Details:** +- **Queue Key Pattern:** Must use sequential numerical keys (0, 1, 2, etc.) - NOT push IDs +- **Order Management:** Queue items must maintain sequential order with automatic validation +- **Controller Initialization:** Empty controller structure created if none exists +- **Listener Management:** All Firebase listeners must be properly cleaned up +- **Error Recovery:** Graceful handling of Firebase sync failures with retry patterns +- **Type Safety:** All data must be validated against TypeScript interfaces +- **Performance:** Use specific node subscriptions instead of full controller subscriptions +- **Memory Management:** Proper cleanup of observers, listeners, and subscriptions + +### **Firebase Schema Requirements:** +- **Controller Structure:** Must match the exact structure defined in `types.ts` +- **Key Format:** Queue items must use sequential numerical keys +- **Data Types:** All data must conform to TypeScript interfaces +- **Required Fields:** Critical fields must be present for operations to succeed +- **Default Values:** Empty controller must have all required fields with default values + +### **Migration & Compatibility:** +- **Key Migration:** Automatic migration of push ID keys to sequential numerical keys +- **Order Fixing:** Automatic repair of inconsistent queue order values +- **Backward Compatibility:** Support for existing data with inconsistent keys +- **Data Validation:** Runtime validation of data structure integrity + +--- + +## 18. Critical Implementation Notes + +### **DO NOT CHANGE These Patterns:** +- **Queue Key Management:** Sequential numerical keys (0, 1, 2, etc.) - changing this will break queue functionality +- **Controller Structure:** Exact structure must match `types.ts` - changing will break sync +- **Service Layer Pattern:** All Firebase operations must go through service modules +- **Subscription Pattern:** Real-time updates must use subscribe/unsubscribe pattern +- **Error Handling:** Service-level error handling with console logging must be maintained +- **Type Safety:** All data validation against TypeScript interfaces must be preserved +- **Connection Management:** FirebaseProvider pattern with connection status tracking +- **Cleanup Management:** Proper cleanup of listeners and subscriptions + +### **Critical Dependencies:** +- **Firebase Config:** Must be properly configured with environment variables +- **TypeScript Interfaces:** Must match exactly with Firebase data structure +- **Redux State:** Must maintain consistency with Firebase data +- **Service Functions:** Must handle all error cases and provide proper cleanup +- **Hook Dependencies:** Must include proper dependency arrays for useEffect hooks + +### **Performance Requirements:** +- **List Pagination:** All lists must use infinite scroll with 20 items per page +- **Memory Management:** Proper cleanup of all listeners and observers +- **Efficient Queries:** Use specific node subscriptions, not full controller subscriptions +- **Optimistic Updates:** UI updates immediately with rollback on error +- **Debounced Operations:** Search and filter operations must be debounced + +### **Error Recovery Patterns:** +- **Graceful Degradation:** App must continue working with cached data during connection issues +- **Retry Logic:** Automatic retry for failed Firebase operations +- **User Feedback:** Clear error messages with recovery options +- **Data Validation:** Runtime validation with fallback values +- **Connection Monitoring:** Real-time connection status with error state management + +--- + +## βœ… Summary + +This PRD serves as the comprehensive source of truth for application logic, Firebase data flow, and feature requirements. +It works alongside `types.ts` and `firebase_schema.json` to inform both human developers and AI tools for accurate implementation. + +**Key Success Metrics:** +- βœ… **Real-time Sync:** All users see updates within 1 second +- βœ… **Performance:** App loads in under 3 seconds on mobile +- βœ… **Reliability:** 99.9% uptime with graceful error handling +- βœ… **User Experience:** Intuitive interface requiring minimal training +- βœ… **Scalability:** Supports up to 50 concurrent users per session + +--- + +## 19. Environment Configuration & .env.local Setup + +### **Environment File Structure:** +The application uses Vite's built-in environment variable support with the following file structure: + +``` +project-root/ +β”œβ”€β”€ .env.template # Template file with all required variables +β”œβ”€β”€ .env.local # Local development environment (gitignored) +β”œβ”€β”€ .env.production # Production environment (if needed) +└── .env.staging # Staging environment (if needed) +``` + +### **Required Environment Variables:** + +#### **Firebase Configuration (Required):** +```bash +# Firebase Configuration +VITE_FIREBASE_API_KEY=your-api-key +VITE_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com +VITE_FIREBASE_DATABASE_URL=https://your-project-id-default-rtdb.firebaseio.com +VITE_FIREBASE_PROJECT_ID=your-project-id +VITE_FIREBASE_STORAGE_BUCKET=your-project-id.appspot.com +VITE_FIREBASE_MESSAGING_SENDER_ID=123456789 +VITE_FIREBASE_APP_ID=your-app-id +``` + +#### **App Configuration (Optional with defaults):** +```bash +# App Configuration +VITE_CONTROLLER_NAME=default +VITE_APP_TITLE=SingSalot AI +``` + +### **Environment Variable Usage Pattern:** +- **Vite Prefix:** All environment variables must be prefixed with `VITE_` to be accessible in the client-side code +- **Fallback Values:** All environment variables have fallback values in `src/constants/index.ts` +- **Type Safety:** Environment variables are accessed via `import.meta.env.VITE_*` +- **Build-time Injection:** Variables are injected at build time, not runtime + +### **Configuration Loading Pattern:** +```typescript +// src/constants/index.ts +export const FIREBASE_CONFIG = { + apiKey: import.meta.env.VITE_FIREBASE_API_KEY || 'your-api-key', + authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || 'your-project-id.firebaseapp.com', + databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL || 'https://your-project-id-default-rtdb.firebaseio.com', + projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || 'your-project-id', + storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || 'your-project-id.appspot.com', + messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || '123456789', + appId: import.meta.env.VITE_FIREBASE_APP_ID || 'your-app-id', +}; + +export const CONTROLLER_NAME = import.meta.env.VITE_CONTROLLER_NAME || 'default'; +``` + +### **Setup Instructions:** + +#### **1. Initial Setup:** +```bash +# Copy the template file +cp .env.template .env.local + +# Edit .env.local with your actual Firebase configuration +nano .env.local +``` + +#### **2. Firebase Configuration:** +1. Go to Firebase Console β†’ Project Settings +2. Copy the configuration values from the "General" tab +3. Replace the placeholder values in `.env.local` + +#### **3. Controller Configuration:** +- `VITE_CONTROLLER_NAME`: Set to your desired controller name (default: "default") +- `VITE_APP_TITLE`: Set to your desired app title (default: "SingSalot AI") + +### **Environment-Specific Configurations:** + +#### **Development (.env.local):** +```bash +# Local development with hot reload +VITE_CONTROLLER_NAME=dev-controller +VITE_APP_TITLE=SingSalot AI (Dev) +``` + +#### **Staging (.env.staging):** +```bash +# Pre-production testing +VITE_CONTROLLER_NAME=staging-controller +VITE_APP_TITLE=SingSalot AI (Staging) +``` + +#### **Production (.env.production):** +```bash +# Live production environment +VITE_CONTROLLER_NAME=production-controller +VITE_APP_TITLE=SingSalot AI +``` + +### **Security Considerations:** +- **Client-Side Exposure:** All `VITE_*` variables are exposed in the client bundle +- **Firebase Security:** Firebase API keys are safe to expose in client-side code +- **Database Rules:** Security is enforced through Firebase Realtime Database Rules +- **Environment Isolation:** Use different Firebase projects for different environments + +### **Build Process Integration:** +- **Development:** Uses `.env.local` automatically when running `npm run dev` +- **Production Build:** Uses `.env.production` when running `npm run build` +- **Environment Detection:** Vite automatically detects the correct environment file +- **Build-time Injection:** Variables are replaced at build time, not runtime + +### **Error Handling for Missing Variables:** +- **Fallback Values:** All variables have sensible defaults +- **Console Warnings:** Missing required variables show console warnings +- **Graceful Degradation:** App continues to work with fallback values +- **Development Feedback:** Clear error messages for missing configuration + +### **Environment Variable Validation:** +```typescript +// Validation pattern used in the app +const validateFirebaseConfig = () => { + const requiredVars = [ + 'VITE_FIREBASE_API_KEY', + 'VITE_FIREBASE_AUTH_DOMAIN', + 'VITE_FIREBASE_DATABASE_URL', + 'VITE_FIREBASE_PROJECT_ID' + ]; + + const missing = requiredVars.filter(varName => !import.meta.env[varName]); + + if (missing.length > 0) { + console.warn('Missing Firebase configuration:', missing); + } +}; +``` + +### **Deployment Considerations:** +- **CI/CD Integration:** Environment variables must be set in deployment pipeline +- **Build Commands:** Different build commands for different environments +- **Environment Files:** `.env.local` is gitignored, other files may be committed +- **Secret Management:** Use deployment platform's secret management for production + +### **Troubleshooting:** +- **Variable Not Found:** Ensure variable name starts with `VITE_` +- **Build Issues:** Check that all required variables are set +- **Runtime Errors:** Verify Firebase configuration is correct +- **Environment Detection:** Ensure correct `.env` file is being used + +### **Best Practices:** +- **Template File:** Always maintain `.env.template` with all required variables +- **Documentation:** Document all environment variables and their purposes +- **Validation:** Implement runtime validation for critical configuration +- **Fallbacks:** Provide sensible default values for all variables +- **Security:** Never commit sensitive values to version control + +--- + +## 23. Complete Data Flow Diagrams + +### **Authentication Flow:** +``` +1. User enters Party ID + Name +2. Validate Party ID exists in Firebase +3. If valid: dispatch setAuth action +4. If invalid: show error message "Invalid Party Id. Please check your Party Id and try again." +5. On auth success: initialize Firebase sync +6. Load complete controller object +7. If controller doesn't exist: create empty structure +8. Clean up admin URL parameter if present +``` + +### **Queue Operations Flow:** +``` +Add to Queue: +1. User clicks "Add to Queue" on song +2. Validate controller name and current singer exist +3. Calculate next order: Math.max(existingOrders) + 1 +4. Create queue item with sequential key +5. Call queueService.addToQueue() +6. Firebase updates in real-time +7. All clients receive updated queue +8. Show success toast + +Remove from Queue: +1. User clicks remove (admin only, when not playing) +2. Validate admin permissions and playback state +3. Call queueService.removeFromQueue() +4. Firebase removes item +5. All clients receive updated queue +6. Show success toast + +Reorder Queue: +1. Admin clicks reorder buttons +2. Validate admin permissions and playback state +3. Calculate new order values for affected items +4. Update all affected items atomically with Promise.all() +5. Firebase updates in real-time +6. All clients receive updated queue +7. Show success toast +``` + +### **Search Flow:** +``` +1. User types in search input +2. Debounce 300ms before processing +3. If < 2 characters: show all songs (filtered by disabled songs) +4. If >= 2 characters: filter songs by search term +5. Apply multi-word logic (AND for multiple terms, OR for single term) +6. Filter out disabled songs +7. Paginate results (20 items per page) +8. Show results with infinite scroll +9. Reset to page 1 when search term changes +``` + +### **Real-time Sync Flow:** +``` +1. User authenticates successfully +2. FirebaseProvider initializes +3. Subscribe to controller node: `controllers/${controllerName}` +4. On data change: dispatch setController action +5. Redux updates state +6. Components re-render with new data +7. On unmount: cleanup Firebase listeners +``` + +--- + +## 24. State Management Architecture + +### **Redux State Tree Structure:** +```typescript +{ + auth: { + data: { + authenticated: boolean, + singer: string, + isAdmin: boolean, + controller: string + } | null, + loading: boolean, + error: string | null + }, + controller: { + data: { + favorites: Record, + history: Record, + topPlayed: Record, + newSongs: Record, + disabledSongs: Record, + player: { + queue: Record, + settings: { + autoadvance: boolean, + userpick: boolean + }, + singers: Record, + state: { + state: PlayerState + } + }, + songList: Record, + songs: Record + } | null, + loading: boolean, + error: string | null, + lastUpdated: number | null + } +} +``` + +### **Key Selectors (Memoized):** +```typescript +// Authentication +selectIsAuthenticated: (state) => state.auth.data?.authenticated +selectControllerName: (state) => state.auth.data?.controller +selectCurrentSinger: (state) => state.auth.data?.singer +selectIsAdmin: (state) => state.auth.data?.isAdmin + +// Controller Data +selectController: (state) => state.controller.data +selectSongs: (state) => state.controller.data?.songs +selectQueue: (state) => state.controller.data?.player.queue +selectFavorites: (state) => state.controller.data?.favorites +selectHistory: (state) => state.controller.data?.history +selectTopPlayed: (state) => state.controller.data?.topPlayed +selectNewSongs: (state) => state.controller.data?.newSongs +selectDisabledSongs: (state) => state.controller.data?.disabledSongs +selectSettings: (state) => state.controller.data?.player.settings +selectSingers: (state) => state.controller.data?.player.singers +selectPlayerState: (state) => state.controller.data?.player.state + +// Derived Data +selectSongsArray: createSelector([selectSongs], (songs) => + sortSongsByArtistAndTitle(objectToArray(songs)) +) +selectQueueWithUserInfo: createSelector([selectQueue, selectCurrentSinger], (queue, currentSinger) => + addUserInfoToQueue(queue, currentSinger) +) +selectQueueLength: createSelector([selectQueue], (queue) => + Object.keys(queue || {}).length +) +``` + +### **Action Types:** +```typescript +// Auth Actions +setAuth: Authentication +setLoading: boolean +setError: string +clearError: void +logout: void +updateSinger: string +setAdminStatus: boolean + +// Controller Actions +setController: Controller +updateSongs: Record +updateQueue: Record +updateFavorites: Record +updateHistory: Record +updateTopPlayed: Record +clearError: void +resetController: void +``` + +--- + +## 25. Service Layer API Specifications + +### **Controller Service:** +```typescript +controllerService.getController(controllerName: string): Promise +- Validates: controllerName is non-empty string +- Returns: Complete controller object or null if not exists +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +controllerService.setController(controllerName: string, data: Controller): Promise +- Validates: controllerName and data are provided +- Action: Overwrites entire controller object +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +controllerService.updateController(controllerName: string, updates: Partial): Promise +- Validates: controllerName and updates are provided +- Action: Updates specific parts of controller +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +controllerService.subscribeToController(controllerName: string, callback: (data: Controller | null) => void): () => void +- Validates: controllerName and callback are provided +- Action: Sets up real-time listener +- Returns: Unsubscribe function +- Throws: Error if listener setup fails +- Timeout: None (Firebase handles) +``` + +### **Queue Service:** +```typescript +queueService.addToQueue(controllerName: string, queueItem: Omit): Promise<{ key: string }> +- Validates: controllerName, queueItem with required fields +- Calculates: Next sequential key (Math.max(existingKeys) + 1) +- Action: Adds item to queue with sequential key +- Returns: { key: string } with the new key +- Throws: Error if validation fails or Firebase operation fails +- Timeout: None (Firebase handles) + +queueService.removeFromQueue(controllerName: string, queueItemKey: string): Promise +- Validates: controllerName and queueItemKey are provided +- Action: Removes item from queue +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +queueService.updateQueueItem(controllerName: string, queueItemKey: string, updates: Partial): Promise +- Validates: controllerName, queueItemKey, and updates are provided +- Action: Updates specific fields of queue item +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +queueService.cleanupQueueKeys(controllerName: string): Promise +- Validates: controllerName is provided +- Action: Migrates push ID keys to sequential numerical keys +- Logic: Find non-numerical keys, assign sequential keys, update atomically +- Returns: void +- Throws: Error if migration fails +- Timeout: None (Firebase handles) + +queueService.subscribeToQueue(controllerName: string, callback: (data: Record) => void): () => void +- Validates: controllerName and callback are provided +- Action: Sets up real-time listener for queue changes +- Returns: Unsubscribe function +- Throws: Error if listener setup fails +- Timeout: None (Firebase handles) +``` + +### **Disabled Songs Service:** +```typescript +disabledSongsService.generateSongKey(songPath: string): string +- Validates: songPath is non-empty string +- Algorithm: Simple hash function ((hash << 5) - hash) + charCodeAt(i) +- Returns: Base36 string for Firebase-safe key +- Throws: None (pure function) + +disabledSongsService.addDisabledSong(controllerName: string, song: Song): Promise +- Validates: controllerName, song.path, song.artist, song.title +- Action: Adds song to disabled list with hash key +- Returns: void +- Throws: Error if validation fails or Firebase operation fails +- Timeout: 10 seconds + +disabledSongsService.removeDisabledSong(controllerName: string, songPath: string): Promise +- Validates: controllerName and songPath are provided +- Action: Removes song from disabled list +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: 10 seconds + +disabledSongsService.isSongDisabled(controllerName: string, songPath: string): Promise +- Validates: controllerName and songPath are provided +- Action: Checks if song is in disabled list +- Returns: boolean +- Throws: Error if Firebase operation fails +- Timeout: 10 seconds + +disabledSongsService.getDisabledSongs(controllerName: string): Promise> +- Validates: controllerName is provided +- Action: Gets all disabled songs +- Returns: Record of disabled songs +- Throws: Error if Firebase operation fails +- Timeout: 10 seconds + +disabledSongsService.getDisabledSongPaths(controllerName: string): Promise> +- Validates: controllerName is provided +- Action: Gets disabled song paths as Set for fast lookup +- Returns: Set of disabled song paths +- Throws: Error if Firebase operation fails +- Timeout: 10 seconds + +disabledSongsService.subscribeToDisabledSongs(controllerName: string, callback: (data: Record) => void): () => void +- Validates: controllerName and callback are provided +- Action: Sets up real-time listener for disabled songs +- Returns: Unsubscribe function +- Throws: Error if listener setup fails +- Timeout: None (Firebase handles) +``` + +### **Singer Service:** +```typescript +singerService.addSinger(controllerName: string, singerName: string): Promise<{ key: string }> +- Validates: controllerName and singerName are non-empty, trimmed +- Checks: Case-insensitive duplicate prevention +- Action: Adds singer with current timestamp +- Returns: { key: string } with Firebase push key +- Throws: Error if validation fails, duplicate exists, or Firebase operation fails +- Timeout: None (Firebase handles) + +singerService.removeSinger(controllerName: string, singerName: string): Promise +- Validates: controllerName and singerName are provided +- Action: Removes singer and their queue items +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +singerService.subscribeToSingers(controllerName: string, callback: (data: Record) => void): () => void +- Validates: controllerName and callback are provided +- Action: Sets up real-time listener for singers +- Returns: Unsubscribe function +- Throws: Error if listener setup fails +- Timeout: None (Firebase handles) +``` + +### **Player Service:** +```typescript +playerService.updatePlayerStateValue(controllerName: string, state: PlayerState): Promise +- Validates: controllerName and state are provided +- Action: Updates player state +- Returns: void +- Throws: Error if Firebase operation fails +- Timeout: None (Firebase handles) + +playerService.subscribeToPlayerState(controllerName: string, callback: (data: Player) => void): () => void +- Validates: controllerName and callback are provided +- Action: Sets up real-time listener for player state +- Returns: Unsubscribe function +- Throws: Error if listener setup fails +- Timeout: None (Firebase handles) +``` + +--- + +## 26. Component Architecture Specifications + +### **SongItem Component:** +```typescript +interface SongItemProps { + song: Song; + context: 'search' | 'queue' | 'history' | 'favorites' | 'topPlayed' | 'newSongs'; + onAddToQueue?: (song: Song) => void; + onRemoveFromQueue?: (queueItem: QueueItem) => void; + onToggleFavorite?: (song: Song) => void; + onDelete?: (song: Song) => void; + onSelectSinger?: (song: Song) => void; + isAdmin?: boolean; + className?: string; + showActions?: boolean; + showPath?: boolean; + showCount?: boolean; + showInfoButton?: boolean; + showAddButton?: boolean; + showRemoveButton?: boolean; + showDeleteButton?: boolean; + showFavoriteButton?: boolean; +} + +Event Flow: +1. User clicks action button +2. Component calls prop function (e.g., onAddToQueue) +3. Hook handles business logic (useSongOperations) +4. Service updates Firebase (queueService.addToQueue) +5. Real-time listener updates Redux +6. Component re-renders with new data +7. Toast notification shows success/error +``` + +### **InfiniteScrollList Component:** +```typescript +interface InfiniteScrollListProps { + items: any[]; + context: 'search' | 'queue' | 'history' | 'favorites' | 'topPlayed' | 'newSongs'; + isLoading: boolean; + hasMore: boolean; + onLoadMore: () => void; + renderItem: (item: any, index: number) => React.ReactNode; + className?: string; + debug?: boolean; +} + +Behavior: +1. Renders items with renderItem function +2. Shows loading spinner when isLoading && items.length === 0 +3. Shows empty state when items.length === 0 && !isLoading +4. Shows load more trigger when hasMore && items.length > 0 +5. Uses Intersection Observer to detect when user scrolls to bottom 10% +6. Calls onLoadMore when trigger is visible +7. Cleans up observer on unmount +``` + +### **ActionButton Component:** +```typescript +interface ActionButtonProps { + onClick: () => void; + children: React.ReactNode; + variant?: 'primary' | 'secondary' | 'danger'; + size?: 'sm' | 'md' | 'lg'; + disabled?: boolean; + icon?: string; + className?: string; +} + +Behavior: +1. Renders button with variant styling +2. Shows icon if provided +3. Disables button when disabled prop is true +4. Calls onClick when clicked +5. Supports different sizes and variants +``` + +### **PlayerControls Component:** +```typescript +interface PlayerControlsProps { + className?: string; + variant?: 'light' | 'dark'; +} + +Behavior: +1. Only renders for admin users (selectIsAdmin) +2. Shows current player state with color-coded badge +3. Play button: disabled when queue is empty +4. Pause button: only shown when playing +5. Stop button: only shown when playing or paused +6. Calls playerService.updatePlayerStateValue on button clicks +7. Shows success/error toasts for feedback +``` + +### **Component Hierarchy:** +``` +App +β”œβ”€β”€ ErrorBoundary +β”œβ”€β”€ FirebaseProvider +β”œβ”€β”€ Router +β”œβ”€β”€ AuthInitializer +β”œβ”€β”€ Layout +β”‚ β”œβ”€β”€ Navigation +β”‚ └── Routes +β”‚ β”œβ”€β”€ Search +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ Queue +β”‚ β”‚ β”œβ”€β”€ PlayerControls +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ Favorites +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ History +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ TopPlayed +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ NewSongs +β”‚ β”‚ └── InfiniteScrollList +β”‚ β”‚ └── SongItem +β”‚ β”œβ”€β”€ Artists +β”‚ β”‚ └── ArtistModal +β”‚ β”œβ”€β”€ SongLists +β”‚ β”‚ └── SongListModal +β”‚ β”œβ”€β”€ Singers +β”‚ └── Settings +└── Toast (global) +``` + +--- + +## 27. Error Handling Matrix + +### **Network Errors:** +``` +Firebase Connection Lost: +- Detection: onValue error callback +- Action: Show connection status indicator +- Recovery: Automatic retry with exponential backoff +- User Feedback: "Connection lost. Retrying..." + +Firebase Timeout (10s): +- Detection: Promise.race with timeout +- Action: Show error toast +- Recovery: Allow manual retry +- User Feedback: "Operation timed out. Please try again." + +Network Unavailable: +- Detection: navigator.onLine or fetch error +- Action: Show offline indicator +- Recovery: Queue operations for when online +- User Feedback: "You're offline. Changes will sync when connected." +``` + +### **Validation Errors:** +``` +Party ID Invalid: +- Detection: Firebase get() returns null +- Action: Show error message +- Recovery: Allow user to retry +- User Feedback: "Invalid Party Id. Please check your Party Id and try again." + +Singer Name Empty: +- Detection: singerName.trim().length === 0 +- Action: Highlight input field +- Recovery: Prevent form submission +- User Feedback: "Singer name cannot be empty" + +Singer Already Exists: +- Detection: Case-insensitive name comparison +- Action: Show error toast +- Recovery: Allow user to choose different name +- User Feedback: "Singer already exists" + +Required Fields Missing: +- Detection: Check for undefined/null values +- Action: Highlight missing fields +- Recovery: Prevent operation +- User Feedback: "Please fill in all required fields" +``` + +### **Permission Errors:** +``` +Admin Action by Non-Admin: +- Detection: selectIsAdmin === false +- Action: Hide admin-only UI elements +- Recovery: Show permission error +- User Feedback: "Only admins can perform this action" + +Delete During Playback: +- Detection: playerState.state === 'playing' +- Action: Disable delete buttons +- Recovery: Allow delete when stopped/paused +- User Feedback: "Cannot delete while playing" +``` + +### **Concurrent Conflicts:** +``` +Queue Reorder Conflict: +- Detection: Order values don't match expected sequence +- Action: Auto-fix order values +- Recovery: Update all items with sequential order +- User Feedback: "Queue order has been corrected" + +Singer Add Conflict: +- Detection: Duplicate name (case-insensitive) +- Action: Prevent addition +- Recovery: Show error message +- User Feedback: "Singer already exists" + +Settings Change Conflict: +- Detection: Multiple users changing settings simultaneously +- Action: Last write wins +- Recovery: Show conflict notification +- User Feedback: "Settings updated by another user" +``` + +### **Data Corruption:** +``` +Invalid Queue Order: +- Detection: Order values not sequential (1, 2, 3, ...) +- Action: Auto-fix order values +- Recovery: Update all items with correct order +- User Feedback: "Queue order has been corrected" + +Missing Required Fields: +- Detection: Required fields are undefined/null +- Action: Use default values or skip item +- Recovery: Log error and continue +- User Feedback: "Some data could not be loaded" + +Invalid Firebase Keys: +- Detection: Non-numerical keys in queue +- Action: Run cleanupQueueKeys() +- Recovery: Migrate to sequential keys +- User Feedback: "Queue has been updated" +``` + +--- + +## 28. Performance Specifications + +### **Memoization Rules:** +```typescript +// Redux Selectors (Always Memoize) +selectSongsArray: createSelector([selectSongs], (songs) => + sortSongsByArtistAndTitle(objectToArray(songs)) +) + +selectQueueWithUserInfo: createSelector([selectQueue, selectCurrentSinger], (queue, currentSinger) => + addUserInfoToQueue(queue, currentSinger) +) + +// Component Props (Memoize Expensive Calculations) +const filteredSongs = useMemo(() => + filterSongs(allSongs, searchTerm, disabledSongPaths), + [allSongs, searchTerm, disabledSongPaths] +) + +// Event Handlers (Use useCallback for Async Operations) +const handleAddToQueue = useCallback(async (song: Song) => { + await addToQueue(song); +}, [addToQueue]); + +const handleRemoveFromQueue = useCallback(async (queueItem: QueueItem) => { + await removeFromQueue(queueItem); +}, [removeFromQueue]); +``` + +### **Bundle Splitting Strategy:** +```typescript +// Route-based Splitting +const Search = lazy(() => import('./features/Search/Search')); +const Queue = lazy(() => import('./features/Queue/Queue')); +const Favorites = lazy(() => import('./features/Favorites/Favorites')); +const History = lazy(() => import('./features/History/History')); +const TopPlayed = lazy(() => import('./features/TopPlayed/Top100')); +const NewSongs = lazy(() => import('./features/NewSongs/NewSongs')); +const Artists = lazy(() => import('./features/Artists/Artists')); +const SongLists = lazy(() => import('./features/SongLists/SongLists')); +const Singers = lazy(() => import('./features/Singers/Singers')); +const Settings = lazy(() => import('./features/Settings/Settings')); + +// Component-based Splitting +const ArtistModal = lazy(() => import('./components/common/ArtistModal')); +const SongListModal = lazy(() => import('./components/common/SongListModal')); + +// Vendor Splitting +// Third-party libraries (Ionic, Firebase) in separate chunks +``` + +### **Virtual Scrolling (Future Implementation):** +```typescript +// For lists with 1000+ items +interface VirtualScrollConfig { + itemHeight: number; + overscan: number; + containerHeight: number; +} + +// Only render visible items + buffer +const visibleItems = items.slice(startIndex, endIndex + overscan); +``` + +### **Image Optimization:** +```typescript +// Lazy load images +const LazyImage = ({ src, alt, ...props }) => { + const [isLoaded, setIsLoaded] = useState(false); + const [isInView, setIsInView] = useState(false); + + useEffect(() => { + if (isInView) { + const img = new Image(); + img.onload = () => setIsLoaded(true); + img.src = src; + } + }, [isInView, src]); + + return ( +
+ {!isLoaded && } + {isInView && {alt}} +
+ ); +}; +``` + +### **Firebase Optimization:** +```typescript +// Specific node subscriptions instead of full controller +const queueRef = ref(database, `controllers/${controllerName}/player/queue`); +const favoritesRef = ref(database, `controllers/${controllerName}/favorites`); + +// Batch operations for multiple updates +const updates = {}; +updates[`controllers/${controllerName}/player/queue/${key1}`] = item1; +updates[`controllers/${controllerName}/player/queue/${key2}`] = item2; +await update(ref(database), updates); +``` + +### **Memory Management:** +```typescript +// Cleanup listeners on unmount +useEffect(() => { + const unsubscribe = subscribeToQueue(controllerName, callback); + return () => unsubscribe(); +}, [controllerName]); + +// Cleanup observers +useEffect(() => { + const observer = new IntersectionObserver(callback, options); + observer.observe(element); + return () => observer.disconnect(); +}, []); +``` + +--- + +## 29. Implementation Guide for New Projects + +### **Quick Start Questions for Implementation:** + +When starting a new implementation, ask these questions to determine the approach: + +#### **1. Platform Target:** +- **Web:** Browser-based application +- **iOS:** Native iOS app (Swift/SwiftUI) +- **Android:** Native Android app (Kotlin/Jetpack Compose) +- **Cross-platform:** Single codebase for multiple platforms (Flutter, React Native) + +#### **2. Framework Choice (Based on Platform):** +- **Web:** React, Vue, Svelte, Angular +- **iOS:** SwiftUI, UIKit +- **Android:** Jetpack Compose, Views +- **Cross-platform:** Flutter, React Native + +#### **3. State Management:** +- **Centralized:** Redux, Zustand, Pinia, Jotai +- **Local:** React Context, Vue Composition API +- **Platform-specific:** SwiftUI @State, Jetpack Compose StateFlow + +#### **4. UI Framework:** +- **Web:** Ionic, Chakra UI, Material UI, Ant Design +- **Native:** Platform-specific components +- **Cross-platform:** Framework-specific UI libraries + +#### **5. Backend/Data:** +- **Firebase:** Realtime Database, Firestore +- **Supabase:** PostgreSQL with real-time +- **AWS:** AppSync, DynamoDB +- **Custom:** REST API with WebSockets + +#### **6. Build Tool:** +- **Web:** Vite, Webpack, Parcel +- **iOS:** Xcode +- **Android:** Android Studio +- **Cross-platform:** Framework-specific tools + +#### **7. Styling:** +- **Web:** Tailwind CSS, CSS Modules, Styled Components +- **Native:** Platform-specific styling +- **Cross-platform:** Framework-specific styling + +### **Implementation Checklist:** + +#### **Phase 1: Project Setup** +- [ ] Create project with chosen framework/tools +- [ ] Set up Firebase/backend configuration +- [ ] Configure state management +- [ ] Set up routing/navigation +- [ ] Configure build tools and deployment + +#### **Phase 2: Core Architecture** +- [ ] Implement service layer (all Firebase operations) +- [ ] Set up state management (Redux slices/selectors) +- [ ] Create base components (SongItem, ActionButton, etc.) +- [ ] Implement authentication flow +- [ ] Set up real-time sync + +#### **Phase 3: Feature Implementation** +- [ ] Search functionality with disabled songs filtering +- [ ] Queue management with sequential keys +- [ ] Favorites system +- [ ] History tracking +- [ ] Top played with cloud functions +- [ ] Singer management +- [ ] Player controls +- [ ] Settings and disabled songs +- [ ] Artists and song lists + +#### **Phase 4: Error Handling & Performance** +- [ ] Implement error handling matrix +- [ ] Add performance optimizations +- [ ] Set up bundle splitting +- [ ] Add loading states and empty states +- [ ] Implement infinite scroll + +#### **Phase 5: Testing & Polish** +- [ ] Test all business logic +- [ ] Verify real-time sync +- [ ] Test error scenarios +- [ ] Performance testing +- [ ] UI/UX polish + +### **Key Implementation Notes:** + +#### **Must Preserve (Regardless of Framework):** +- **Business Logic:** All validation rules, calculations, and data flows +- **Service Layer:** All Firebase operations with exact signatures +- **State Structure:** Same data organization and relationships +- **Error Handling:** All error scenarios and recovery strategies +- **Performance:** Memoization, bundle splitting, and optimization patterns + +#### **Can Replace (Framework-Specific):** +- **UI Components:** Replace with framework-equivalent components +- **State Management Library:** Replace Redux with framework-appropriate solution +- **Styling:** Replace Tailwind with framework-appropriate styling +- **Build Tools:** Replace Vite with framework-appropriate build system + +#### **Critical Success Factors:** +- **Follow data flow diagrams exactly** +- **Implement all service functions with exact signatures** +- **Maintain same state structure and relationships** +- **Handle all error scenarios from the matrix** +- **Preserve all business logic and validation rules** + +--- + +## 20. Third-Party UI Library - Ionic React + +### **Current UI Implementation:** +The application currently uses **Tailwind CSS** for styling with custom components. While functional, this approach requires significant custom development for responsive design and native platform feel. + +### **Recommended Solution: Ionic React** + +For a **mobile-first app that works on web**, **Ionic React** is the single best choice because it provides native platform feel across all devices while maintaining web compatibility. + +#### **Installation:** +```bash +npm install @ionic/react @ionic/core +``` + +#### **Why Ionic React:** +- **Mobile-First:** Designed specifically for mobile experiences +- **Native Feel:** Mimics iOS and Android native components automatically +- **Web Compatible:** Works perfectly on desktop browsers +- **Touch Optimized:** Built-in touch interactions and gestures +- **Responsive:** Automatic responsive design without custom CSS +- **Accessibility:** Excellent accessibility support out of the box +- **Performance:** Optimized for mobile performance +- **Simple:** One library handles everything - no complex configuration + +#### **Integration Pattern:** +```typescript +// src/components/common/IonicButton.tsx +import { IonButton, IonIcon } from '@ionic/react'; +import { add, heart, play } from 'ionicons/icons'; + +export const ActionButton: React.FC = ({ + onClick, + children, + variant = 'primary', + icon, + disabled = false +}) => { + const getVariant = () => { + switch (variant) { + case 'primary': return 'primary'; + case 'secondary': return 'medium'; + case 'danger': return 'danger'; + default: return 'primary'; + } + }; + + return ( + + {icon && } + {children} + + ); +}; +``` + +#### **Responsive Design (Automatic):** +```typescript +// Ionic handles responsive design automatically +export const SongList: React.FC = () => { + return ( + + {songs.map(song => ( + + +

{song.title}

+

{song.artist}

+
+ + + +
+ ))} +
+ ); +}; +``` + +#### **Navigation (Mobile-First):** +```typescript +// Ionic provides mobile-optimized navigation +export const AppNavigation: React.FC = () => { + return ( + + + + + Queue + + + + Search + + + + Favorites + + + + ); +}; +``` + +#### **Touch Interactions (Built-in):** +```typescript +// Ionic provides touch-optimized interactions automatically +export const SwipeableSongItem: React.FC = ({ + song, + onDelete +}) => { + return ( + + + +

{song.title}

+

{song.artist}

+
+
+ + onDelete(song.id)}> + + + +
+ ); +}; +``` + +### **Migration Strategy (Simple):** + +#### **Step 1: Install and Setup (1 day)** +```bash +npm install @ionic/react @ionic/core +``` + +Add to `src/main.tsx`: +```typescript +import { setupIonicReact } from '@ionic/react'; + +setupIonicReact(); +``` + +#### **Step 2: Replace Core Components (3-4 days)** +- Replace `ActionButton` with `IonButton` +- Replace custom lists with `IonList` and `IonItem` +- Replace modals with `IonModal` +- Replace toasts with `IonToast` + +#### **Step 3: Update Navigation (1 day)** +- Replace custom navigation with `IonTabs` or `IonMenu` +- Mobile gets bottom tabs, desktop gets side menu automatically + +#### **Step 4: Add Touch Features (1 day)** +- Add swipe-to-delete with `IonItemSliding` +- Add pull-to-refresh with `IonRefresher` +- Add infinite scroll with `IonInfiniteScroll` + +### **Benefits Over Current Approach:** + +#### **Before (Tailwind CSS):** +- ❌ Custom responsive CSS for every component +- ❌ Manual touch interaction implementation +- ❌ Custom mobile navigation +- ❌ Manual accessibility features +- ❌ Complex responsive breakpoints + +#### **After (Ionic React):** +- βœ… Automatic responsive design +- βœ… Built-in touch interactions +- βœ… Mobile-optimized navigation +- βœ… Accessibility built-in +- βœ… Native platform feel +- βœ… Works on all devices automatically + +### **Performance:** +- **Bundle Size:** ~50KB gzipped (minimal overhead) +- **Mobile Performance:** Optimized for mobile devices +- **Web Performance:** Works great on desktop browsers +- **Loading:** Fast initial load with lazy loading + +### **Accessibility:** +- **Screen Readers:** Full support out of the box +- **Keyboard Navigation:** Complete keyboard support +- **Touch Targets:** Proper 44px minimum touch targets +- **WCAG Compliance:** Built-in accessibility standards + +### **Implementation Timeline:** +- **Day 1:** Install and basic setup +- **Days 2-5:** Replace core components +- **Day 6:** Update navigation +- **Day 7:** Add touch features and testing + +### **Success Metrics:** +- **Mobile Performance:** 90+ Lighthouse score +- **Touch Responsiveness:** <100ms response time +- **Accessibility:** WCAG 2.1 AA compliance +- **User Experience:** Native app feel on mobile +- **Web Compatibility:** Perfect desktop experience + +### **Why Not Other Libraries:** +- **Chakra UI:** Great for web, but requires custom mobile optimization +- **Material-UI:** Enterprise-focused, overkill for this app +- **Custom Tailwind:** Too much work for responsive design and touch interactions + +### **Simple Decision:** +**Use Ionic React** - it's the only library that gives you: +1. Mobile-first design automatically +2. Native platform feel +3. Perfect web compatibility +4. Built-in touch interactions +5. Zero configuration responsive design + +No complex choices, no multiple libraries, no over-engineering. Just one library that does everything you need for a mobile-first karaoke app. + +--- + +## 21. Design Assets & Visual Reference + +### **Design Assets Location:** +The `/docs/design/` folder contains comprehensive UI/UX mockups and visual references for different platforms and features. + +### **Current Web Design Assets:** +Located in `/docs/design/web/` with 30+ mockups covering all features: + +#### **Core Navigation & Layout:** +- `00-web-layout.JPG` - Overall web layout structure +- `01-Login.png` - Login screen design +- `02-menu.jpeg`, `02a-menu.jpeg`, `02b-menu.png`, `02c-menu.jpeg` - Navigation menu variations + +#### **Queue Management:** +- `02-queue.png` - Main queue view +- `02-queue-delete.png` - Queue with delete functionality +- `02-queue-drag.png` - Queue reordering with drag and drop +- `02-queue-sorting.png` - Queue sorting interface + +#### **Search & Discovery:** +- `04-search.png` - Main search interface +- `04-search typing .png` - Search with typing interaction +- `04-search-song info.png` - Search results with song information + +#### **User Management:** +- `05-singers.png` - Singer list view +- `05-singers add.png` - Singer management interface + +#### **Content Browsing:** +- `06-artists .png` - Artist browse interface +- `06-artists (not admin).png` - Non-admin artist view +- `06-artists search.png` - Artist search functionality +- `06-artists songs.png` - Artist songs list + +#### **User Features:** +- `07-favorites.png` - Favorites management +- `08-history.png` - Play history view +- `09-songs list.png` - Main song lists view +- `09-song lists - songs.png` - Song lists with song details +- `09- song lists songs expand.png` - Song lists with expandable sections + +#### **Admin Features:** +- `10-Settings.png` - Settings interface +- `11-top 100.png` - Top played songs +- `12-favorites .png` - Favorites view +- `12-favorite lists.png` - Favorite lists management + +#### **Menu States:** +- `03-menu.png` - General menu layout +- `03-menu current page and non-admin.png` - Navigation with current page indicators +- `03-menu playing (admin).png` - Admin view during playback + +### **Future Platform Design Structure:** +``` +design/ +β”œβ”€β”€ web/ # Current web mockups (30+ files) +β”œβ”€β”€ ios/ # Future iOS designs (SwiftUI/UIKit) +β”œβ”€β”€ android/ # Future Android designs (Jetpack Compose/Views) +β”œβ”€β”€ tablet/ # Future tablet designs (iPad/Android tablets) +└── desktop/ # Future desktop designs (Windows/macOS) +``` + +### **Design Asset Guidelines:** +- **Reference during implementation** for visual accuracy +- **Understand UX patterns** and interaction flows +- **Guide UI component design** and layout decisions +- **Ensure consistency** across different implementations +- **Validate feature completeness** against visual requirements + +### **Important Note About Current Web Mockups:** +The web mockups were created using an **older version of Ionic** and may not reflect the current Ionic React component API or styling. However, they serve as valuable reference for: + +#### **Layout Intent:** +- **Overall Structure:** How the app should be organized +- **Navigation Flow:** User journey through different screens +- **Component Placement:** Where buttons, lists, and controls should be positioned +- **Information Hierarchy:** How data should be prioritized and displayed + +#### **User Experience Goals:** +- **Mobile-First Design:** Touch-friendly interface elements +- **Intuitive Navigation:** Clear paths between features +- **Context-Aware Actions:** Different actions based on user role and context +- **Real-time Updates:** Visual indicators for live data changes + +### **Implementation Considerations:** + +#### **Modern Ionic React vs Mockups:** +```typescript +// Mockup shows older Ionic syntax + + Add to Queue + + +// Modern Ionic React syntax (current recommendation) + + + Add to Queue + +``` + +#### **Component Mapping:** +| Mockup Component | Modern Ionic React Component | +|------------------|------------------------------| +| Old Button | `IonButton` with `fill` prop | +| Old List | `IonList` with `IonItem` | +| Old Modal | `IonModal` with `IonHeader` | +| Old Navigation | `IonTabs` or `IonMenu` | +| Old Toast | `IonToast` with `position` prop | + +#### **Styling Updates:** +- **Colors:** Modern Ionic uses semantic color names +- **Spacing:** Updated spacing system for better mobile experience +- **Typography:** Improved font scaling for accessibility +- **Touch Targets:** Enhanced minimum touch target sizes + +### **Using Mockups for Implementation:** + +#### **1. Layout Reference:** +- Use mockups to understand the intended layout structure +- Follow the visual hierarchy shown in the designs +- Maintain the component relationships and positioning + +#### **2. Feature Requirements:** +- Identify required functionality from mockups +- Understand user interaction patterns +- Note admin vs user permission differences + +#### **3. User Flow Validation:** +- Verify navigation paths match mockup flow +- Ensure all screens are implemented +- Confirm user roles and permissions are correctly applied + +#### **4. Modern Implementation:** +- Use current Ionic React components and syntax +- Apply modern responsive design principles +- Implement current accessibility standards +- Follow current performance best practices + +### **Migration from Mockups to Modern Ionic:** + +#### **Step 1: Component Analysis** +- Review each mockup for required components +- Map to current Ionic React component library +- Identify any custom components needed + +#### **Step 2: Layout Implementation** +- Implement responsive layouts using modern Ionic grid +- Use current Ionic spacing and sizing system +- Apply modern touch interaction patterns + +#### **Step 3: Feature Implementation** +- Build features using current Ionic React APIs +- Implement modern state management patterns +- Apply current performance optimization techniques + +#### **Step 4: Testing and Refinement** +- Test on actual mobile devices +- Verify touch interactions work correctly +- Ensure accessibility compliance +- Optimize for performance + +### **Key Differences to Note:** + +#### **Navigation:** +- **Mockups:** May show older navigation patterns +- **Modern:** Use `IonTabs` for bottom navigation on mobile +- **Modern:** Use `IonMenu` for side navigation on desktop + +#### **Lists:** +- **Mockups:** May show older list styling +- **Modern:** Use `IonList` with `IonItem` for better performance +- **Modern:** Implement `IonItemSliding` for swipe actions + +#### **Forms:** +- **Mockups:** May show older form components +- **Modern:** Use `IonInput`, `IonSelect`, etc. for better UX +- **Modern:** Implement proper form validation + +#### **Modals:** +- **Mockups:** May show older modal patterns +- **Modern:** Use `IonModal` with proper backdrop handling +- **Modern:** Implement proper focus management + +### **Recommendation:** +1. **Use mockups as layout and UX reference** +2. **Implement using current Ionic React components** +3. **Follow modern responsive design principles** +4. **Test on actual devices for touch interactions** +5. **Ensure accessibility and performance compliance** + +The mockups provide excellent guidance for the intended user experience, but the implementation should use current Ionic React best practices and components. + +--- + +## 22. Development Setup & Configuration + diff --git a/docs/PRD.md b/docs/PRD.md index 0b051b7..e2093a3 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -1,23 +1,28 @@ -# 🎀 Karaoke App β€” Product Requirements Document (PRD) +# Karaoke App - Product Requirements Document + +> **Platform-Agnostic Business Logic & Firebase Architecture** +> **For implementation details, see platform-specific PRDs in `platforms/` folder** + +This document defines the **core business logic, data models, and Firebase architecture** for the Karaoke App. All platform-specific implementation details are documented in separate platform PRDs. --- -## πŸš€ How to Use This PRD +## How to Use This PRD -**For AI Implementation:** When you read this PRD, please: -1. **Read the entire document completely** - it contains comprehensive technical specifications -2. **Ask the 7 implementation questions** from Section 29 to determine platform/framework choices -3. **Follow the implementation checklist** from Section 29 for the complete build process -4. **Preserve all business logic** while adapting UI to the chosen framework -5. **Use the exact specifications** for data flows, service APIs, and error handling +### **For AI-Assisted Development:** +1. **Read this PRD completely** for core business logic and Firebase structure +2. **Choose your platform** and read the corresponding platform PRD: + - **Web:** `platforms/web/PRD-web.md` + - **iOS:** `platforms/ios/PRD-ios.md` (future) + - **Android:** `platforms/android/PRD-android.md` (future) +3. **Follow the implementation guide** in Section 29 +4. **Reference design assets** in the platform-specific design folder -**For Human Developers:** This PRD contains complete technical specifications including data flows, state management, service APIs, component architecture, error handling, and performance optimizations. It's designed for 100% accuracy when building from scratch. - ---- - -> **Note:** This PRD is structured for platform-agnostic use. Each feature is described with platform-independent requirements, followed by a 'Web Implementation Details' section for web-specific behaviors. For future platforms (iOS, Android, etc.), add corresponding implementation details under each feature. This ensures the PRD can be used as the single source of truth for any platform. -> -> **Toolset/Framework Sections:** Each platform implementation includes explicit toolset/framework choices with rationale. This preserves the "why" behind current choices while enabling seamless migration to new technologies. When migrating, replace the toolset section while keeping the core requirements intact. +### **For Human Developers:** +- **Reference during implementation** for business logic and data flows +- **Guide for architecture decisions** and technology choices +- **Source of truth** for all functional requirements +- **Migration guide** when switching frameworks/platforms --- @@ -25,259 +30,242 @@ This document defines the functional, technical, and UX requirements for the Karaoke App, designed for **in-home party use**. The app leverages **Firebase Realtime Database** for real-time synchronization, with all business logic and validation handled **client-side**. +### **Core Principles:** +- **Platform-Agnostic Design** - Core requirements work on any platform +- **Real-time Synchronization** - All clients stay in sync via Firebase +- **Client-Side Business Logic** - All validation and rules enforced in app +- **Single Session Focus** - Designed for one-party-at-a-time use +- **Admin/User Role System** - Different permissions for different users + --- ## 2. Scope & Business Objectives -- Deliver a single-session karaoke experience where users connect to a controller and manage/search songs. -- Use Firebase for real-time multi-user sync of queues, history, and playback state. -- Prioritize fast performance, reusable modular architecture, and clear business logic separation. -- Enable adding songs from multiple entry points (search, history, top played, favorites, new songs, artists, song lists). -- Ensure graceful handling of Firebase sync issues using retry patterns and partial node updates. -- True Separation of Concerns - UI components only handle presentation -- Reusable Business Logic - Hooks can be used across components -- Testable Code - Business logic separated from UI -- Maintainable - Changes to logic don't affect UI -- Performance - Memoized selectors and optimized hooks -- Type Safety - Full TypeScript coverage throughout -- The codebase needs to follow the Single Responsibility Principle perfectly - each file has one clear purpose! +### **Primary Goals:** +- Deliver a single-session karaoke experience where users connect to a controller and manage/search songs +- Utilize Firebase for real-time multi-user synchronization of queues, history, and playback state +- Prioritize fast performance, reusable modular architecture, and clear business logic separation +- Enable adding songs from multiple entry points (search, history, top played, favorites, new songs, artists, song lists) +- Ensure graceful handling of Firebase sync issues using retry patterns and partial node updates ---- - -## 2.5️⃣ Toolset & Framework Choices - -### **Current Web Implementation Toolset:** - -#### **Core Framework: React 18 + TypeScript** -- **Why:** Component-based architecture, strong ecosystem, excellent TypeScript support -- **Migration Note:** Can be replaced with any component-based framework (Vue, Svelte, etc.) - -#### **State Management: Redux Toolkit** -- **Why:** Centralized state management, predictable state updates, excellent dev tools -- **Key Requirements:** Must support real-time sync, optimistic updates, and complex state relationships -- **Migration Note:** Can be replaced with Zustand, Jotai, Valtio, or any state management solution that supports: - - Centralized state - - Real-time updates - - Optimistic updates - - Complex selectors - -#### **UI Framework: Ionic React** -- **Why:** Mobile-first design, native feel, excellent accessibility, built-in components -- **Key Requirements:** Must support responsive design, touch interactions, and accessibility -- **Migration Note:** Can be replaced with any UI framework that provides: - - Responsive components - - Touch-optimized interactions - - Accessibility support - - Modal/dialog components - - List components with infinite scroll - -#### **Styling: Tailwind CSS** -- **Why:** Utility-first CSS, rapid development, consistent design system -- **Migration Note:** Can be replaced with any CSS solution (CSS Modules, Styled Components, etc.) - -#### **Build Tool: Vite** -- **Why:** Fast development server, optimized builds, excellent TypeScript support -- **Migration Note:** Can be replaced with any modern build tool (Webpack, Parcel, etc.) - -#### **Backend: Firebase Realtime Database** -- **Why:** Real-time sync, simple setup, excellent for collaborative apps -- **Key Requirements:** Must support real-time listeners, offline capabilities, and complex queries -- **Migration Note:** Can be replaced with any real-time database (Supabase, AWS AppSync, etc.) - -#### **Cloud Functions: Firebase Functions** -- **Why:** Serverless, integrates with Firebase, automatic scaling -- **Migration Note:** Can be replaced with any serverless platform (AWS Lambda, Vercel Functions, etc.) - -### **Architecture Patterns:** - -#### **Service Layer Pattern** -- **Why:** Separation of concerns, testable business logic, reusable across components -- **Implementation:** All Firebase operations abstracted into service modules -- **Migration Note:** Must maintain service layer pattern regardless of backend choice - -#### **Hook Pattern** -- **Why:** Reusable business logic, separation of UI and logic, testable -- **Implementation:** Custom hooks for each feature (useQueue, useSearch, etc.) -- **Migration Note:** Can be replaced with any pattern that separates business logic from UI - -#### **Component Composition** -- **Why:** Reusable components, clear separation of concerns, maintainable -- **Implementation:** Common components (SongItem, ActionButton, etc.) used across features -- **Migration Note:** Must maintain component composition regardless of framework choice +### **Architecture Principles:** +- **True Separation of Concerns** - UI components only handle presentation +- **Reusable Business Logic** - Business rules implemented in platform-agnostic services +- **Testable Code** - Business logic separated from UI for easy testing +- **Maintainability** - Changes to logic don't affect UI +- **Performance** - Optimized data access and state management +- **Type Safety** - Strong typing throughout the codebase +- **Single Responsibility** - Each file has one clear purpose --- ## 3. User Roles & Permissions -**Requirements (Platform-Agnostic):** -- Two roles: Host/Admin and Singer/User. -- Only admins can reorder or delete queue items, control playback, and manage singers. -- Admin access is a privileged mode (see platform details for how it's triggered). -- First queue item cannot be deleted while playing (only when stopped/paused). -- Singers are automatically added to the singers list when they join. +### **Core Requirements (Platform-Agnostic):** -**Web Implementation Details:** -- Admin access is triggered by a URL parameter (`?admin=true`) and removed from the URL after login. -- Session is lost on browser reload. +#### **Two User Roles:** +1. **Host/Admin** - Full control over the karaoke session +2. **Singer/User** - Can add songs and view content + +#### **Admin Permissions:** +- **Queue Management** - Reorder or delete queue items +- **Playback Control** - Play, pause, stop the music +- **Singer Management** - Add or remove singers +- **Settings Access** - Change player settings (autoadvance, userpick) +- **Song Management** - Disable or enable songs + +#### **User Permissions:** +- **Add Songs** - Add songs to queue from any source +- **View Content** - Browse songs, history, favorites, etc. +- **Manage Favorites** - Add/remove personal favorites + +#### **Business Rules:** +- **First Queue Item Protection** - Cannot be deleted while playing (only when stopped/paused) +- **Automatic Singer Addition** - Singers are automatically added to the list when they join +- **Admin Access Control** - Admin mode is a privileged state (see platform details for implementation) + +#### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#authentication` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#authentication` (future) +- **Android:** See `platforms/android/PRD-android.md#authentication` (future) --- ## 4. Feature Overview -### Authentication & Session Management +### **Authentication & Session Management** **Requirements (Platform-Agnostic):** -- Login requires both Party ID and singer name. -- Party ID is validated against the backend before login is allowed. -- Authentication state is managed in the app state and lost on app reload (unless platform supports persistence). +- Login requires both Party ID and singer name +- Party ID is validated against the backend before login is allowed +- Authentication state is managed in the app state and lost on app reload (unless platform supports persistence) +- Admin access is a privileged mode (see platform details for implementation) -**Web Implementation Details:** -- Admin access via URL parameter (`?admin=true`), removed after login. -- Session is lost on browser reload. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#authentication` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#authentication` (future) +- **Android:** See `platforms/android/PRD-android.md#authentication` (future) -### Search +### **Search** **Requirements (Platform-Agnostic):** -- Local search on preloaded song catalog. -- Instant search results as user types. -- Paginated/infinite scroll results. -- Context actions for each song (add to queue, favorite, etc). +- Local search on preloaded song catalog +- Instant search results as user types +- Paginated/infinite scroll results +- Context actions for each song (add to queue, favorite, etc.) -**Web Implementation Details:** -- Uses Ionic InfiniteScrollList for pagination. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#search` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#search` (future) +- **Android:** See `platforms/android/PRD-android.md#search` (future) -### Queue Management +### **Queue Management** **Requirements (Platform-Agnostic):** -- Shared queue synchronized across all clients. -- Queue items must always use sequential numerical keys (0, 1, 2, ...). -- The system must automatically fix any inconsistencies in order values or keys on every update. -- Queue reordering must be atomic; when two items are swapped, both order values are updated in a single operation. -- Only admins can reorder or delete queue items, and only when playback is stopped or paused. -- Duplicate songs are prevented in the queue by checking the song’s `path`. -- Each queue item shows which singer added it. +- Shared queue synchronized across all clients +- Queue items must always use sequential numerical keys (0, 1, 2, ...) +- The system must automatically fix any inconsistencies in order values or keys on every update +- Queue reordering must be atomic; when two items are swapped, both order values are updated in a single operation +- Only admins can reorder or delete queue items, and only when playback is stopped or paused +- Duplicate songs are prevented in the queue by checking the song's `path` +- Each queue item shows which singer added it -**Web Implementation Details:** -- Queue reordering and deletion are exposed via UI controls only visible to admins. -- UI uses drag handles and swipe actions (Ionic components) for reordering and deletion. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#queue-management` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#queue-management` (future) +- **Android:** See `platforms/android/PRD-android.md#queue-management` (future) -### Favorites +### **Favorites** **Requirements (Platform-Agnostic):** -- Shared favorites list synchronized across all clients. -- Anyone can add/remove favorites. -- Duplicate prevention by song `path`. -- Paginated/infinite scroll display. +- Shared favorites list synchronized across all clients +- Anyone can add/remove favorites +- Duplicate prevention by song `path` +- Paginated/infinite scroll display -**Web Implementation Details:** -- Uses Ionic InfiniteScrollList for pagination. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#favorites` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#favorites` (future) +- **Android:** See `platforms/android/PRD-android.md#favorites` (future) -### New Songs +### **New Songs** **Requirements (Platform-Agnostic):** -- Shows recently added songs from the `newSongs` node. -- Real-time updates and infinite scroll. +- Shows recently added songs from the `newSongs` node +- Real-time updates and infinite scroll -**Web Implementation Details:** -- Uses Ionic InfiniteScrollList for pagination. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#new-songs` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#new-songs` (future) +- **Android:** See `platforms/android/PRD-android.md#new-songs` (future) -### Artists +### **Artists** **Requirements (Platform-Agnostic):** -- Browse songs by artist with search functionality. -- Modal view for all songs by an artist. -- Song count per artist. -- Paginated/infinite scroll artist list. +- Browse songs by artist with search functionality +- Modal view for all songs by an artist +- Song count per artist +- Paginated/infinite scroll artist list -**Web Implementation Details:** -- Uses Ionic modals and InfiniteScrollList. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#artists` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#artists` (future) +- **Android:** See `platforms/android/PRD-android.md#artists` (future) -### Song Lists +### **Song Lists** **Requirements (Platform-Agnostic):** -- Predefined song lists with themes/collections. -- Song matching to catalog. -- Expandable view for available versions. -- Modal interface for viewing list contents. -- Shows which songs are available in the catalog. +- Predefined song lists with themes/collections +- Song matching to catalog +- Expandable view for available versions +- Modal interface for viewing list contents +- Shows which songs are available in the catalog -**Web Implementation Details:** -- Uses Ionic modals and InfiniteScrollList. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#song-lists` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#song-lists` (future) +- **Android:** See `platforms/android/PRD-android.md#song-lists` (future) -### History Tracking +### **History Tracking** **Requirements (Platform-Agnostic):** -- Songs automatically added to history when played. -- Shows when each song was last played. -- Append-only, shared across all clients. -- Paginated/infinite scroll display. +- Songs automatically added to history when played +- Shows when each song was last played +- Append-only, shared across all clients +- Paginated/infinite scroll display -**Web Implementation Details:** -- Uses Ionic InfiniteScrollList for pagination. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#history` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#history` (future) +- **Android:** See `platforms/android/PRD-android.md#history` (future) -### Top Played +### **Top Played** **Requirements (Platform-Agnostic):** -- Popular songs generated by backend based on history. -- Shows play count for each song. -- Real-time updates and infinite scroll. +- Popular songs generated by backend based on history +- Shows play count for each song +- Real-time updates and infinite scroll -**Web Implementation Details:** -- Uses Ionic InfiniteScrollList for pagination. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#top-played` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#top-played` (future) +- **Android:** See `platforms/android/PRD-android.md#top-played` (future) -### Singer Management +### **Singer Management** **Requirements (Platform-Agnostic):** -- Only admins can add or remove singers. -- Singer names must be unique and non-empty. -- Singers are automatically added to the list when they join. -- All users can view the current singers list. -- Tracks when each singer last joined. +- Only admins can add or remove singers +- Singer names must be unique and non-empty +- Singers are automatically added to the list when they join +- All users can view the current singers list +- Tracks when each singer last joined -**Web Implementation Details:** -- Singer management UI is available only to admins via the settings page. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#singer-management` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#singer-management` (future) +- **Android:** See `platforms/android/PRD-android.md#singer-management` (future) -### Playback Control +### **Playback Control** **Requirements (Platform-Agnostic):** -- Only admins can control playback (play, pause, stop). -- Play button is disabled if the queue is empty. -- UI state (play/pause/stop) must reflect the current player state. +- Only admins can control playback (play, pause, stop) +- Play button is disabled if the queue is empty +- UI state (play/pause/stop) must reflect the current player state -**Web Implementation Details:** -- Player controls are only rendered for admins. -- State-based UI: play/pause/stop buttons shown/hidden based on current state. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#playback-control` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#playback-control` (future) +- **Android:** See `platforms/android/PRD-android.md#playback-control` (future) -### Error Handling & Sync +### **Error Handling & Sync** **Requirements (Platform-Agnostic):** -- Graceful handling of sync failures with retry patterns. -- Full controller object loaded on initial connection. -- Incremental updates target specific child nodes. -- Real-time connection status monitoring. -- Graceful handling of missing or empty data. +- Graceful handling of sync failures with retry patterns +- Full controller object loaded on initial connection +- Incremental updates target specific child nodes +- Real-time connection status monitoring +- Graceful handling of missing or empty data -**Web Implementation Details:** -- Uses web-specific toast notifications and error boundaries. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#error-handling` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#error-handling` (future) +- **Android:** See `platforms/android/PRD-android.md#error-handling` (future) -### Disabled Songs +### **Disabled Songs** **Requirements (Platform-Agnostic):** -- Admins can disable or enable songs. -- Disabled songs are stored using a hash of the song path for key safety. +- Admins can disable or enable songs +- Disabled songs are stored using a hash of the song path for key safety -**Web Implementation Details:** -- Disabled songs are managed via a modal dialog with search and filter capabilities. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#disabled-songs` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#disabled-songs` (future) +- **Android:** See `platforms/android/PRD-android.md#disabled-songs` (future) -### Settings +### **Settings** **Requirements (Platform-Agnostic):** -- Only admins can change player settings (autoadvance, userpick). +- Only admins can change player settings (autoadvance, userpick) -**Web Implementation Details:** -- Debug logging is a web-only feature, toggled via the settings page. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#settings` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#settings` (future) +- **Android:** See `platforms/android/PRD-android.md#settings` (future) -### Navigation +### **Navigation** **Requirements (Platform-Agnostic):** -- Admin-only pages (e.g., settings) must be hidden from non-admin users. +- Admin-only pages (e.g., settings) must be hidden from non-admin users -**Web Implementation Details:** -- Navigation adapts based on admin status; settings page is only visible to admins. - -### UI/UX & Platform-Specifics -**Requirements (Platform-Agnostic):** -- All business logic, validation, and permissions must be enforced at the application level, not just in the UI. - -**Web Implementation Details:** -- The web implementation uses Ionic React and Tailwind CSS for UI. -- Features like infinite scroll, swipe actions, modals, and toasts are implemented using Ionic components. -- Session persistence, URL parameter handling, and debug logging are web-specific. +**Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#navigation` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#navigation` (future) +- **Android:** See `platforms/android/PRD-android.md#navigation` (future) --- @@ -311,7 +299,7 @@ This file contains TypeScript interfaces describing: Defined externally in: > [`firebase_schema.json`](./firebase_schema.json) -**Complete Structure:** +### **Complete Structure:** ```json controllers: { [controllerName]: { @@ -332,13 +320,13 @@ controllers: { } ``` -**Data Flow:** +### **Data Flow:** - **Initial Sync:** Loads the complete `controller` object on connection - **Real-time Updates:** Subscribes to specific nodes for incremental updates - **Key Management:** Uses sequential numerical keys for queue items - **Auto-initialization:** Creates empty controller structure if none exists -**Empty Controller Structure:** +### **Empty Controller Structure:** ```json { "favorites": {}, @@ -362,13 +350,13 @@ controllers: { } ``` -**Key Generation Rules:** +### **Key Generation Rules:** - **Queue Items:** Sequential numerical keys (0, 1, 2, ...) - **Top Played:** `sanitizedArtist_sanitizedTitle` (lowercase, trimmed, invalid chars replaced with `_`) - **Disabled Songs:** Hash of song path (simple character-based hash) - **Singers:** Firebase push IDs (auto-generated) -**Character Sanitization for Top Played Keys:** +### **Character Sanitization for Top Played Keys:** - Replace invalid Firebase characters `[.#$/[\]]` with `_` - Convert to lowercase and trim whitespace - Format: `${sanitizedArtist}_${sanitizedTitle}` @@ -377,115 +365,106 @@ controllers: { ## 7. UI/UX Behavior -**Requirements (Platform-Agnostic):** -- Responsive design that works on all device sizes. -- Support for light/dark mode themes. -- Modern, clean, intuitive interface with consistent styling. -- Accessibility support (keyboard navigation, screen readers). -- Tab-based navigation with clear active states. -- Consistent empty state views for all lists. -- Loading states with spinner animations. -- Toast notifications for success/error feedback. -- Consistent button styling with variants. -- Reusable song display with context-aware actions. -- Infinite scroll for automatic loading of additional content. -- Context-specific behavior for different screens (search, queue, history, etc.). -- Admin-specific UI elements (playback controls, queue reorder, singer management). +### **Core Requirements (Platform-Agnostic):** +- **Responsive design** that works on all device sizes +- **Support for light/dark mode** themes +- **Modern, clean, intuitive interface** with consistent styling +- **Accessibility support** (keyboard navigation, screen readers) +- **Tab-based navigation** with clear active states +- **Consistent empty state views** for all lists +- **Loading states** with spinner animations +- **Toast notifications** for success/error feedback +- **Consistent button styling** with variants +- **Reusable song display** with context-aware actions +- **Infinite scroll** for automatic loading of additional content +- **Context-specific behavior** for different screens (search, queue, history, etc.) +- **Admin-specific UI elements** (playback controls, queue reorder, singer management) -**Web Implementation Details:** -- Uses Ionic React components for responsive design and accessibility. -- Horizontal navigation bar with icons. -- Toast notifications positioned at top-right corner. -- Modal views for artist songs and song lists. -- Drag handles and swipe actions for queue management. +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#uiux-behavior` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#uiux-behavior` (future) +- **Android:** See `platforms/android/PRD-android.md#uiux-behavior` (future) --- ## 8. UI Rules & Constraints -**Requirements (Platform-Agnostic):** +### **Core Requirements (Platform-Agnostic):** -### **Queue Management Rules:** -- Only admin users can reorder queue items. -- First queue item cannot be deleted while playing (only when stopped/paused). -- Reorder constraints: items not at top/bottom can move up/down. -- Queue items must maintain sequential order (1, 2, 3, etc.). -- Automatic cleanup of inconsistent order values on queue initialization. -- Queue items use sequential numerical keys (0, 1, 2, etc.). +#### **Queue Management Rules:** +- Only admin users can reorder queue items +- First queue item cannot be deleted while playing (only when stopped/paused) +- Reorder constraints: items not at top/bottom can move up/down +- Queue items must maintain sequential order (1, 2, 3, etc.) +- Automatic cleanup of inconsistent order values on queue initialization +- Queue items use sequential numerical keys (0, 1, 2, etc.) -### **Playback Control Rules:** -- Player controls only visible to admin users. -- Play button is disabled when queue is empty. -- State-based controls: play/pause/stop buttons shown/hidden based on current state. -- Current player state must be clearly displayed. +#### **Playback Control Rules:** +- Player controls only visible to admin users +- Play button is disabled when queue is empty +- State-based controls: play/pause/stop buttons shown/hidden based on current state +- Current player state must be clearly displayed -### **Search Rules:** -- Search only activates after 2+ characters. -- Debounce delay before search execution. -- Search scope includes both song title and artist fields (case-insensitive). -- Empty search shows all songs. -- Search resets to page 1 when search term changes. +#### **Search Rules:** +- Search only activates after 2+ characters +- Debounce delay before search execution +- Search scope includes both song title and artist fields (case-insensitive) +- Empty search shows all songs +- Search resets to page 1 when search term changes -### **Pagination & Infinite Scroll Rules:** -- 20 items loaded per page. -- Load more logic only shows when there are more items than currently displayed. -- Triggers load more when user scrolls to bottom 10% of list. -- Each feature maintains its own page state independently. -- All lists must use pagination to prevent UI blocking. -- Progressive loading of items as user scrolls. -- Loading state management with spinner when no items are loaded yet. -- Page reset on search term changes. -- Memory optimization for smooth scrolling. -- Error handling for load more failures. -- Accessibility support for infinite scroll. +#### **Pagination & Infinite Scroll Rules:** +- 20 items loaded per page +- Load more logic only shows when there are more items than currently displayed +- Triggers load more when user scrolls to bottom 10% of list +- Each feature maintains its own page state independently +- All lists must use pagination to prevent UI blocking +- Progressive loading of items as user scrolls +- Loading state management with spinner when no items are loaded yet +- Page reset on search term changes +- Memory optimization for smooth scrolling +- Error handling for load more failures +- Accessibility support for infinite scroll -### **Toast Notification Rules:** -- Duration settings: Success/Info 3 seconds, Error 5 seconds. -- Auto-dismiss after duration. -- Manual dismiss option. -- Multiple toasts can be displayed simultaneously. +#### **Toast Notification Rules:** +- Duration settings: Success/Info 3 seconds, Error 5 seconds +- Auto-dismiss after duration +- Manual dismiss option +- Multiple toasts can be displayed simultaneously -### **Authentication Rules:** -- Admin access is a privileged mode (see platform details for implementation). -- Session persistence behavior varies by platform. -- Both Party ID and singer name required for login. +#### **Authentication Rules:** +- Admin access is a privileged mode (see platform details for implementation) +- Session persistence behavior varies by platform +- Both Party ID and singer name required for login -### **Data Display Rules:** -- Loading states with spinner when data count is 0. -- Empty states when data exists but filtered results are empty. -- Debug information display for development. -- User attribution indicators for current user's queue items. -- Availability status for unmatched song list items. +#### **Data Display Rules:** +- Loading states with spinner when data count is 0 +- Empty states when data exists but filtered results are empty +- Debug information display for development +- User attribution indicators for current user's queue items +- Availability status for unmatched song list items -### **Action Button Rules:** -- Context-based actions for different screens. -- Permission-based visibility based on user role. -- State-based disabling of buttons. -- Confirmation feedback for all actions. +#### **Action Button Rules:** +- Context-based actions for different screens +- Permission-based visibility based on user role +- State-based disabling of buttons +- Confirmation feedback for all actions -### **Modal & Overlay Rules:** -- Modal views for artist songs and song lists. -- Proper backdrop and close actions. +#### **Modal & Overlay Rules:** +- Modal views for artist songs and song lists +- Proper backdrop and close actions -**Web Implementation Details:** -- Admin access via URL parameter (`?admin=true`), removed after authentication. -- Session lost on page reload. -- Uses Ionic InfiniteScrollList component for pagination. -- Toast notifications positioned at top-right corner with z-index 50. -- Modals use high z-index (9999) with semi-transparent backdrop. -- Admin mode pre-fills singer name as "Admin". -- Intersection Observer API for infinite scroll detection. -- Debug information display for development builds. +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#ui-rules` for React/Ionic implementation details +- **iOS:** See `platforms/ios/PRD-ios.md#ui-rules` (future) +- **Android:** See `platforms/android/PRD-android.md#ui-rules` (future) ### **Error Handling Rules:** -- **Error Boundaries:** React error boundaries catch component-level errors - **Graceful Degradation:** App continues to work with cached data during connection issues - **User Feedback:** Clear error messages with recovery options - **Retry Logic:** Automatic retry for failed Firebase operations - **Fallback Values:** Default values provided for missing or corrupted data ### **Performance Rules:** -- **Memoization:** Expensive operations memoized with `useMemo` and `useCallback` - **Debouncing:** Search input debounced to prevent excessive API calls - **Incremental Loading:** Large datasets loaded in chunks via infinite scroll - **Optimistic Updates:** UI updates immediately, with rollback on error @@ -498,2135 +477,263 @@ controllers: { - **Order Validation:** Queue order automatically fixed if inconsistencies detected - **Key Cleanup:** Inconsistent Firebase keys automatically migrated to sequential format -### **Feature Flag Rules:** -- **Configurable Features:** Features can be enabled/disabled via constants: - - `ENABLE_SEARCH: true` - - `ENABLE_QUEUE_REORDER: true` - - `ENABLE_FAVORITES: true` - - `ENABLE_HISTORY: true` - - `ENABLE_TOP_PLAYED: true` - - `ENABLE_ADMIN_CONTROLS: true` - -### **Constants & Limits:** -- **Queue Limits:** Maximum 100 items (`MAX_ITEMS: 100`) -- **History Limits:** Maximum 50 items (`MAX_ITEMS: 50`) -- **Top Played Limits:** Maximum 20 items (`MAX_ITEMS: 20`) -- **Search Limits:** Minimum 2 characters, 300ms debounce -- **Toast Limits:** Success/Info 3s, Error 5s duration - --- ## 9. Codebase Organization & File Structure -### **Folder Structure & Purpose:** +### **Platform-Agnostic Architecture:** +- **Business Logic Layer** - Core rules and validation +- **Data Access Layer** - Firebase operations and data management +- **State Management Layer** - Application state and synchronization +- **UI Layer** - Platform-specific presentation components -| Folder | Purpose | Key Files | Import Pattern | -|--------|---------|-----------|----------------| -| `/components/common` | Shared UI components | `ActionButton.tsx`, `EmptyState.tsx`, `SongItem.tsx`, `InfiniteScrollList.tsx` | `import { ComponentName } from '../components/common'` | -| `/components/Auth` | Authentication components | `AuthInitializer.tsx`, `LoginPrompt.tsx` | `import { AuthInitializer } from '../components/Auth'` | -| `/components/Layout` | Layout and navigation | `Layout.tsx`, `Navigation.tsx` | `import Layout from '../components/Layout/Layout'` | -| `/features` | Feature-specific components | `Search.tsx`, `Queue.tsx`, `History.tsx`, `Artists.tsx`, `SongLists.tsx` | `import { Search, Queue } from '../features'` | -| `/hooks` | Business logic hooks | `useQueue.ts`, `useSearch.ts`, `useSongOperations.ts` | `import { useQueue, useSearch } from '../hooks'` | -| `/redux` | State management | `controllerSlice.ts`, `authSlice.ts`, `selectors.ts` | `import { useAppDispatch, selectQueue } from '../redux'` | -| `/firebase` | Firebase services | `services.ts`, `FirebaseProvider.tsx` | `import { queueService } from '../firebase/services'` | -| `/types` | TypeScript definitions | `index.ts` (extends docs/types.ts) | `import type { Song, QueueItem } from '../types'` | -| `/utils` | Utility functions | `dataProcessing.ts` | `import { filterSongs } from '../utils/dataProcessing'` | -| `/constants` | App constants | `index.ts` | `import { UI_CONSTANTS } from '../constants'` | +### **Required Separation:** +- **UI Components** only handle presentation +- **Business Logic** implemented in platform-agnostic services +- **Data Models** shared across all layers +- **Firebase Integration** abstracted through service layer -### **Index File Pattern:** -Each folder uses an `index.ts` file to export all public APIs: - -```typescript -// src/hooks/index.ts -export { useFirebaseSync } from './useFirebaseSync'; -export { useSongOperations } from './useSongOperations'; -export { useToast } from './useToast'; -export { useSearch } from './useSearch'; -export { useQueue } from './useQueue'; -// ... all other hooks - -// src/components/common/index.ts -export { default as ActionButton } from './ActionButton'; -export { default as EmptyState } from './EmptyState'; -export { default as Toast } from './Toast'; -// ... all other components - -// src/features/index.ts -export { default as Search } from './Search/Search'; -export { default as Queue } from './Queue/Queue'; -export { default as History } from './History/History'; -// ... all other features -``` - -### **Import Organization Patterns:** - -#### **1. Redux Imports:** -```typescript -// Always import from the main redux index -import { useAppDispatch, useAppSelector } from '../redux'; -import { selectQueue, selectSongs } from '../redux'; -import { setController, updateQueue } from '../redux'; - -// Never import directly from slice files -// ❌ import { selectQueue } from '../redux/controllerSlice'; -// βœ… import { selectQueue } from '../redux'; -``` - -#### **2. Hook Imports:** -```typescript -// Import hooks from the main hooks index -import { useQueue, useSearch, useSongOperations } from '../hooks'; - -// Import specific hooks when needed -import { useToast } from '../hooks/useToast'; -``` - -#### **3. Component Imports:** -```typescript -// Import from feature index for feature components -import { Search, Queue, History } from '../features'; - -// Import from common index for shared components -import { ActionButton, EmptyState, SongItem } from '../components/common'; - -// Import layout components directly -import Layout from '../components/Layout/Layout'; -``` - -#### **4. Type Imports:** -```typescript -// Always use type imports for TypeScript interfaces -import type { Song, QueueItem } from '../types'; - -// Import specific types when needed -import type { RootState } from '../types'; -``` - -#### **5. Service Imports:** -```typescript -// Import Firebase services directly -import { queueService, favoritesService } from '../firebase/services'; - -// Import Firebase configuration -import { database } from '../firebase/config'; -``` - -#### **6. Utility Imports:** -```typescript -// Import utility functions directly -import { filterSongs, objectToArray } from '../utils/dataProcessing'; -``` - -#### **7. Constant Imports:** -```typescript -// Import constants from the main constants index -import { UI_CONSTANTS, FEATURES } from '../constants'; -``` - -### **File Organization Principles:** - -#### **Single Responsibility Principle:** -- **Each file has one clear purpose** -- **Hooks handle business logic only** -- **Components handle UI rendering only** -- **Services handle external API calls only** -- **Types define data structures only** - -#### **Separation of Concerns:** -- **UI Components:** Only handle presentation and user interaction -- **Business Logic:** Extracted into custom hooks -- **State Management:** Centralized in Redux slices -- **Data Access:** Abstracted in Firebase services -- **Type Definitions:** Centralized in types folder - -#### **Dependency Direction:** -``` -Components β†’ Hooks β†’ Redux β†’ Services β†’ Firebase - ↓ ↓ ↓ ↓ ↓ - Types ← Types ← Types ← Types ← Types -``` - -### **Redux Architecture Pattern:** - -#### **Slice Organization:** -```typescript -// src/redux/controllerSlice.ts -export const controllerSlice = createSlice({ - name: 'controller', - initialState, - reducers: { - setController: (state, action) => { /* ... */ }, - updateQueue: (state, action) => { /* ... */ }, - // ... other reducers - }, -}); - -// Export actions and selectors -export const { setController, updateQueue } = controllerSlice.actions; -export const selectController = (state: RootState) => state.controller.data; -``` - -#### **Selector Pattern:** -```typescript -// src/redux/selectors.ts -export const selectSongsArray = createSelector( - [selectSongs], - (songs) => sortSongsByArtistAndTitle(objectToArray(songs)) -); - -export const selectQueueWithUserInfo = createSelector( - [selectQueue, selectCurrentSinger], - (queue, currentSinger) => addUserInfoToQueue(queue, currentSinger) -); -``` - -#### **Hook Integration:** -```typescript -// src/hooks/useQueue.ts -export const useQueue = () => { - const queueItems = useAppSelector(selectQueueWithUserInfo); - const dispatch = useAppDispatch(); - - const handleRemoveFromQueue = useCallback(async (queueItemKey: string) => { - try { - await queueService.removeFromQueue(controllerName, queueItemKey); - } catch (error) { - showError('Failed to remove song from queue'); - } - }, [controllerName, showError]); - - return { queueItems, handleRemoveFromQueue }; -}; -``` - -### **Hook Architecture Pattern:** - -#### **Hook Composition:** -```typescript -// Base operations hook -export const useSongOperations = () => { - // Common song operations (add to queue, toggle favorite) -}; - -// Feature-specific hooks compose base hooks -export const useQueue = () => { - const { removeFromQueue, toggleFavorite } = useSongOperations(); - const { showSuccess, showError } = useToast(); - // Queue-specific logic -}; - -export const useSearch = () => { - const { addToQueue, toggleFavorite } = useSongOperations(); - const { showSuccess, showError } = useToast(); - // Search-specific logic -}; -``` - -#### **Hook Dependencies:** -```typescript -// Hooks depend on Redux state and services -export const useQueue = () => { - const queueItems = useAppSelector(selectQueueWithUserInfo); - const { removeFromQueue } = useSongOperations(); - const { showError } = useToast(); - - // Hook logic here -}; -``` - -### **Component Architecture Pattern:** - -#### **Component Structure:** -```typescript -// Feature components are simple and focused -export const Queue = () => { - const { queueItems, handleRemoveFromQueue } = useQueue(); - - return ( -
- -
- ); -}; -``` - -#### **Component Dependencies:** -```typescript -// Components only depend on hooks and UI components -import { useQueue } from '../hooks'; -import { InfiniteScrollList, SongItem } from '../components/common'; -import type { QueueItem } from '../types'; -``` - -### **Type Organization Pattern:** - -#### **Type Definitions:** -```typescript -// src/types/index.ts -export interface Song { - artist: string; - title: string; - path: string; - favorite?: boolean; -} - -export interface QueueItem { - key?: string; - order: number; - singer: Singer; - song: Song; -} - -export interface RootState { - controller: ControllerState; - auth: AuthState; -} -``` - -#### **Type Usage:** -```typescript -// Always use type imports -import type { Song, QueueItem } from '../types'; - -// Use in function parameters and return types -const addToQueue = async (song: Song): Promise => { - // Implementation -}; -``` - -### **Service Architecture Pattern:** - -#### **Service Organization:** -```typescript -// src/firebase/services.ts -export const queueService = { - addToQueue: async (controllerName: string, queueItem: Omit) => { - // Implementation - }, - removeFromQueue: async (controllerName: string, queueItemKey: string) => { - // Implementation - }, - subscribeToQueue: (controllerName: string, callback: (data: Record) => void) => { - // Implementation - }, -}; -``` - -#### **Service Usage:** -```typescript -// Import services directly -import { queueService, favoritesService } from '../firebase/services'; - -// Use in hooks -const handleAddToQueue = useCallback(async (song: Song) => { - await queueService.addToQueue(controllerName, queueItem); -}, [controllerName]); -``` - -### **Constants Organization Pattern:** - -#### **Constants Structure:** -```typescript -// src/constants/index.ts -export const UI_CONSTANTS = { - TOAST_DURATION: { - SUCCESS: 3000, - ERROR: 5000, - INFO: 3000, - }, - SEARCH: { - DEBOUNCE_DELAY: 300, - MIN_SEARCH_LENGTH: 2, - }, -} as const; - -export const FEATURES = { - ENABLE_SEARCH: true, - ENABLE_QUEUE_REORDER: true, -} as const; -``` - -#### **Constants Usage:** -```typescript -// Import constants from main index -import { UI_CONSTANTS, FEATURES } from '../constants'; - -// Use in components and hooks -const debounceDelay = UI_CONSTANTS.SEARCH.DEBOUNCE_DELAY; -``` - -### **Import Order Convention:** -```typescript -// 1. React imports -import { useState, useCallback, useEffect } from 'react'; - -// 2. Third-party library imports -import { useAppSelector, useAppDispatch } from '../redux'; - -// 3. Internal imports (alphabetical by folder) -import { useSongOperations } from '../hooks'; -import { queueService } from '../firebase/services'; -import { UI_CONSTANTS } from '../constants'; -import { filterSongs } from '../utils/dataProcessing'; - -// 4. Type imports -import type { Song, QueueItem } from '../types'; -``` - -### **File Naming Conventions:** -- **Components:** PascalCase (e.g., `SongItem.tsx`, `InfiniteScrollList.tsx`) -- **Hooks:** camelCase with `use` prefix (e.g., `useQueue.ts`, `useSongOperations.ts`) -- **Services:** camelCase with `Service` suffix (e.g., `queueService`, `favoritesService`) -- **Types:** PascalCase (e.g., `Song`, `QueueItem`, `Controller`) -- **Constants:** UPPER_SNAKE_CASE (e.g., `UI_CONSTANTS`, `FEATURES`) -- **Utilities:** camelCase (e.g., `dataProcessing.ts`, `filterSongs`) - -### **Critical Import Rules:** -- **Never import directly from slice files** - always use the main redux index -- **Always use type imports** for TypeScript interfaces -- **Import from index files** for organized modules (hooks, components, features) -- **Import services directly** from their service files -- **Import utilities directly** from their utility files -- **Import constants** from the main constants index +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#codebase-organization` for React/Ionic structure +- **iOS:** See `platforms/ios/PRD-ios.md#codebase-organization` (future) +- **Android:** See `platforms/android/PRD-android.md#codebase-organization` (future) --- -## πŸ”Ÿ Cloud Function Design β€” Top Played - -### **Automatic Top Played Calculation:** -- **Trigger:** Firebase Cloud Function triggered when song added to `history` -- **Action:** Recalculates entire top played list based on history aggregation -- **Benefits:** Non-blocking updates, real-time popularity tracking -- **Data Structure:** Stores artist, title, and count for each popular song - -### **Key Generation Logic:** -- **Format:** `sanitizedArtist_sanitizedTitle` -- **Sanitization:** Replace invalid Firebase characters `[.#$/[\]]` with `_` -- **Processing:** Convert to lowercase and trim whitespace -- **Example:** "AC/DC" + "Back in Black" β†’ "ac_dc_back_in_black" - -### **Aggregation Algorithm:** -- **Group By:** Artist + Title combination (case-insensitive) -- **Count Logic:** Sum all `count` values for same artist/title -- **Sorting:** Sort by count descending, limit to top 100 -- **Data Structure:** Convert array back to object format for Firebase - -### **Manual Recalculation Function:** -- **Function Name:** `recalculateTopPlayed` -- **Trigger:** Manual HTTP callable function -- **Purpose:** Data migration, initial setup, or data repair -- **Input:** `{ controllerName: string }` -- **Output:** Success/failure status with message - -### **Error Handling:** -- **Validation:** Require controllerName parameter -- **Empty Data:** Return empty topPlayed if no history exists -- **Logging:** Console logs for debugging and monitoring - ---- - -## 11. External Reference Files +## 10. External Reference Files | File | Purpose | |------|---------| | [`types.ts`](./types.ts) | Core TypeScript interfaces for data models | -| [`firebase_schema.json`](./firebase_schema.json) | Firebase Realtime Database structure reference | -| [`design/`](./design/) | UI/UX mockups and design specifications | +| [`firebase_schema.json`](./firebase_schema.json) | Complete Firebase database structure | +| `platforms/web/PRD-web.md` | Web-specific implementation details | +| `platforms/web/design/` | Web UI/UX design assets | --- -## 12. Data Access Model & Validation +## 11. Data Access Model & Validation -> **Client-Controlled Access Model** +### **Client-Controlled Access Model:** +- **No server-side validation** - all rules enforced client-side +- **Firebase security rules** allow full read/write access +- **Data validation** against TypeScript interfaces before Firebase writes +- **Business logic** implemented in application layer -This app does **not** use Firebase Realtime Database Security Rules. -All permissions, validation, and business logic are enforced in the client application. - -### **Enforced Client-Side:** -- βœ… **Admin-only permissions** for queue reorder, playback control, and singer management -- βœ… **Duplicate song prevention** enforced before adding to queue/favorites -- βœ… **Singer auto-addition** when users join the session +### **Validation Requirements:** - βœ… **Data validation** against TypeScript interfaces before Firebase writes -- βœ… **Queue order management** with sequential numbering and cleanup -- βœ… **First item protection** preventing deletion during playback +- βœ… **Required field validation** for all critical operations +- βœ… **Duplicate prevention** using song path field +- βœ… **Order validation** for queue items +- βœ… **Permission validation** for admin-only operations -### **Business Logic Validation:** -- **Queue Operations:** Order validation, duplicate prevention, singer attribution -- **Authentication:** Admin mode detection, session management -- **Data Integrity:** Type checking, required field validation -- **State Management:** Redux state consistency, error handling - -**Assumed Environment:** -- The app is used in trusted, in-home scenarios with controlled participants -- Open Firebase access is considered acceptable for this use case -- All users are trusted participants in the karaoke session +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#data-access` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#data-access` (future) +- **Android:** See `platforms/android/PRD-android.md#data-access` (future) --- -## 13. Performance & Optimization +## 12. Performance & Optimization -### **State Management:** -- **Redux Toolkit:** Efficient state management with immutable updates -- **Memoized Selectors:** Optimized data access with `createSelector` -- **Incremental Loading:** Pagination and infinite scroll for large datasets -- **Real-time Sync:** Efficient Firebase subscriptions with cleanup +### **Core Performance Requirements:** +- **Real-time synchronization** with minimal latency +- **Efficient data loading** with pagination and infinite scroll +- **Optimized state management** to prevent unnecessary re-renders +- **Caching strategy** for frequently accessed data +- **Memory management** for large datasets -### **UI Performance:** -- **React.memo:** Component memoization to prevent unnecessary re-renders -- **useCallback/useMemo:** Hook optimization for expensive operations -- **Virtual Scrolling:** Efficient rendering of large lists (implementation pending) -- **Lazy Loading:** Code splitting for better initial load times - -### **Data Optimization:** -- **Efficient Queries:** Optimized Firebase queries with specific node subscriptions -- **Caching Strategy:** Redux state caching with timestamp-based invalidation -- **Batch Operations:** Grouped Firebase updates for better performance -- **Connection Management:** Proper cleanup of Firebase listeners - -### **List Performance & UI Blocking Prevention:** -- **Mandatory Pagination:** All lists MUST use pagination to prevent UI blocking -- **Progressive Rendering:** Only render visible items plus small buffer (20 items per page) -- **Intersection Observer:** Efficient scroll detection without performance impact -- **Memory Management:** Automatic cleanup of observers and event listeners -- **Virtual Scrolling:** Future implementation for very large datasets (1000+ items) -- **Debounced Operations:** Search and filter operations debounced to prevent excessive re-renders -- **Memoized Selectors:** Redux selectors memoized to prevent unnecessary re-computations -- **Optimistic Updates:** UI updates immediately with rollback on error -- **Lazy Loading:** Images and heavy content loaded only when needed -- **Render Optimization:** React.memo and useCallback for expensive operations -- **Bundle Splitting:** Code splitting for better initial load times +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#performance` for React/Ionic optimization +- **iOS:** See `platforms/ios/PRD-ios.md#performance` (future) +- **Android:** See `platforms/android/PRD-android.md#performance` (future) --- -## 14. Error Handling & Resilience +## 13. Error Handling & Resilience -### **Firebase Connection:** -- **Connection Monitoring:** Real-time connection status tracking -- **Retry Logic:** Automatic retry for failed operations +### **Core Error Handling:** +- **Firebase Connection:** Graceful handling of connection issues +- **Data Sync:** Retry patterns for failed operations +- **User Feedback:** Clear error messages with recovery options - **Graceful Degradation:** App continues to work with cached data -- **Error Boundaries:** React error boundaries for component-level error handling -### **Data Validation:** -- **Type Safety:** TypeScript compilation-time error prevention -- **Runtime Validation:** Data structure validation before Firebase writes -- **Fallback Values:** Default values for missing or corrupted data -- **User Feedback:** Clear error messages and recovery options - -### **State Recovery:** -- **Session Persistence:** Authentication state recovery -- **Data Rehydration:** Redux state restoration from Firebase -- **Conflict Resolution:** Handling concurrent user modifications -- **Data Consistency:** Automatic cleanup of inconsistent data structures +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#error-handling` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#error-handling` (future) +- **Android:** See `platforms/android/PRD-android.md#error-handling` (future) --- -## 15. Testing Strategy +## 14. Testing Strategy -### **Unit Testing:** -- **Hook Testing:** Business logic hooks with isolated testing -- **Selector Testing:** Redux selector validation -- **Utility Testing:** Pure function testing for data processing -- **Type Testing:** TypeScript interface validation +### **Core Testing Requirements:** +- **Unit Testing:** Business logic and data validation +- **Integration Testing:** Firebase operations and data flow +- **UI Testing:** User interactions and state changes +- **Performance Testing:** Real-time sync and data loading -### **Integration Testing:** -- **Firebase Integration:** Real-time sync testing -- **Redux Integration:** State management flow testing -- **Component Integration:** UI component interaction testing -- **API Testing:** Firebase service layer testing - -### **E2E Testing:** -- **User Flow Testing:** Complete user journey validation -- **Multi-user Testing:** Concurrent user interaction testing -- **Performance Testing:** Load testing for large datasets -- **Cross-browser Testing:** Browser compatibility validation +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#testing` for React/Ionic testing +- **iOS:** See `platforms/ios/PRD-ios.md#testing` (future) +- **Android:** See `platforms/android/PRD-android.md#testing` (future) --- -## 16. Deployment & Environment +## 15. Deployment & Environment -### **Build Configuration:** -- **Vite:** Fast build tool with hot module replacement -- **TypeScript:** Strict type checking and compilation -- **ESLint:** Code quality and consistency enforcement -- **Tailwind CSS:** Utility-first CSS framework +### **Core Deployment Requirements:** +- **Environment Configuration:** Firebase project setup +- **Build Process:** Platform-specific build tools +- **Environment Variables:** Configuration management +- **Deployment Targets:** Platform-specific deployment -### **Environment Variables:** -- **Firebase Config:** Database connection configuration -- **Controller Name:** Default controller for development -- **Feature Flags:** Environment-specific feature toggles - -### **Deployment Targets:** -- **Development:** Local development with hot reload -- **Staging:** Pre-production testing environment -- **Production:** Live karaoke app deployment +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#deployment` for React/Ionic deployment +- **iOS:** See `platforms/ios/PRD-ios.md#deployment` (future) +- **Android:** See `platforms/android/PRD-android.md#deployment` (future) --- -## 17. Firebase Implementation Patterns +## 16. Firebase Implementation Patterns ### **Key Management & Data Structure:** -- **Sequential Numerical Keys:** Queue items use sequential numerical keys (0, 1, 2, etc.) instead of Firebase push IDs -- **Key Migration:** Automatic cleanup of inconsistent keys (migrate push ID keys to sequential numerical keys) -- **Order Validation:** Queue items maintain sequential order (1, 2, 3, etc.) with automatic cleanup -- **Controller Structure:** Complete controller object loaded on initial connection with empty initialization if not exists +- **Sequential Keys:** Queue items use sequential numerical keys (0, 1, 2, ...) +- **Auto-initialization:** Empty controller structure created if none exists +- **Key Cleanup:** Inconsistent keys automatically migrated to sequential format +- **Order Validation:** Queue order automatically fixed on every update -### **Queue Key Migration Logic:** -- **Cleanup Function:** `cleanupQueueKeys()` migrates push ID keys to sequential numerical keys -- **Key Validation:** Regex pattern `/^\d+$/` to identify numerical keys -- **Migration Strategy:** Find push ID keys, assign sequential keys, update Firebase atomically +### **Real-time Synchronization:** +- **Initial Load:** Complete controller object loaded on connection +- **Incremental Updates:** Specific child nodes updated for efficiency +- **Connection Monitoring:** Real-time connection status tracking +- **Retry Logic:** Automatic retry for failed operations -### **Queue Order Calculation:** -- **Order Logic:** `Math.max(...queueItems.map(item => item.order || 0)) + 1` -- **Fallback Handling:** Use `|| 0` for missing order values -- **Auto-Fix:** Check for inconsistencies on every queue update and fix automatically +### **Data Validation:** +- **Type Safety:** All data validated against TypeScript interfaces +- **Required Fields:** Critical fields validated before Firebase writes +- **Duplicate Prevention:** Songs identified by path field +- **Order Validation:** Queue order automatically fixed -### **Disabled Songs Implementation:** -- **Hash Function:** Simple character-based hash for Firebase-safe keys -- **Hash Algorithm:** `((hash << 5) - hash) + charCodeAt(i)` converted to base36 -- **Timeout Handling:** 10-second timeout for all disabled song operations -- **Validation:** Required fields (controller name, song path, artist, title) -- **Integration:** Filter disabled songs from all search results - -### **Search Algorithm Details:** -- **Multi-word Logic:** AND logic for multiple terms, OR logic for single term -- **Term Processing:** Split on whitespace, filter empty terms -- **Matching:** Case-insensitive includes check on title and artist -- **Disabled Filtering:** Exclude disabled songs from all results -- **Loading States:** Don't show results while disabled songs are loading - -### **Authentication Validation:** -- **Controller Existence Check:** Verify controller exists in Firebase before login -- **Error Messages:** "Invalid Party Id. Please check your Party Id and try again." -- **Field Validation:** Both Party ID and singer name required and trimmed - -### **Singer Name Validation:** -- **Case-insensitive Comparison:** `.toLowerCase()` for duplicate checking -- **Trim Validation:** Remove whitespace from singer names -- **Unique Constraint:** Prevent duplicate singer names (case-insensitive) - -### **Error Handling & Timeouts:** -- **Timeout Values:** 10-second timeout for Firebase operations -- **Specific Error Messages:** "Singer already exists", "Controller not found", etc. -- **Error Recovery:** Handle specific error types with appropriate user feedback - -### **Redux Store Configuration:** -- **Serializable Check:** Disabled for development (`serializableCheck: false`) -- **Immutable Check:** Ignored paths for large data objects -- **Middleware Configuration:** Specific Redux Toolkit settings for performance - -### **Firebase Services Architecture:** -- **Service Layer Pattern:** All Firebase operations abstracted into service modules: - - `controllerService` - Controller CRUD operations - - `queueService` - Queue management with key cleanup - - `playerService` - Player state management - - `historyService` - History operations - - `favoritesService` - Favorites management -- **Subscription Pattern:** Each service provides subscribe/unsubscribe functions for real-time updates -- **Error Handling:** Service functions include try-catch blocks with console logging - -### **Real-time Sync Implementation:** -- **FirebaseProvider Pattern:** Centralized sync management with connection status tracking -- **Full Controller Load:** Initial load of complete controller object on authentication -- **Empty Controller Initialization:** Creates empty controller structure if none exists -- **Connection Status:** Real-time tracking of `isConnected` and `syncStatus` states -- **Cleanup Management:** Proper cleanup of Firebase listeners on unmount - -### **Queue Management Patterns:** -- **Sequential Key Generation:** Next key calculated as `Math.max(existingKeys) + 1` -- **Key Cleanup Function:** `cleanupQueueKeys()` migrates push ID keys to sequential numerical keys -- **Order Calculation:** Next order calculated as `Math.max(existingOrders) + 1` -- **Order Fixing:** Automatic queue order validation and repair in `useQueue` hook -- **Swap Operations:** Queue reordering uses Promise.all for atomic updates - -### **Data Validation & Type Safety:** -- **TypeScript Interfaces:** All data validated against TypeScript interfaces before Firebase writes -- **Required Field Validation:** Critical fields (controller name, singer name) validated before operations -- **Fallback Values:** Default values provided for missing or corrupted data -- **Type Assertions:** Safe type casting with existence checks - -### **Error Handling Patterns:** -- **Service-Level Error Handling:** Each service function includes try-catch with console logging -- **Hook-Level Error Handling:** Custom hooks include error handling with toast notifications -- **Graceful Degradation:** App continues to work with cached data during connection issues -- **Error Boundaries:** React error boundaries for component-level error handling -- **Connection Monitoring:** Real-time connection status with error state management - -### **Performance Optimization Patterns:** -- **Efficient Queries:** Specific node subscriptions instead of full controller subscriptions -- **Listener Cleanup:** Proper cleanup of Firebase listeners to prevent memory leaks -- **Batch Operations:** Grouped Firebase updates using `update()` for better performance -- **Memoized Selectors:** Redux selectors memoized to prevent unnecessary re-computations -- **Incremental Loading:** Large datasets loaded in chunks via infinite scroll - -### **Authentication Integration:** -- **Controller-Based Sessions:** Users connect to specific controller sessions -- **Admin Parameter Handling:** Admin access via URL parameter with automatic cleanup -- **Session Persistence:** Authentication state managed in Redux (lost on page reload) -- **Auto-Initialization:** Empty controller created if none exists for new sessions - -### **Constants & Configuration:** -- **Environment Variables:** Firebase config loaded from environment variables with fallbacks -- **Feature Flags:** Configurable features via constants (ENABLE_SEARCH, ENABLE_QUEUE_REORDER, etc.) -- **UI Constants:** Centralized constants for toast durations, search delays, item limits -- **Error Messages:** Centralized error message constants for consistency - -### **Critical Implementation Details:** -- **Queue Key Pattern:** Must use sequential numerical keys (0, 1, 2, etc.) - NOT push IDs -- **Order Management:** Queue items must maintain sequential order with automatic validation -- **Controller Initialization:** Empty controller structure created if none exists -- **Listener Management:** All Firebase listeners must be properly cleaned up -- **Error Recovery:** Graceful handling of Firebase sync failures with retry patterns -- **Type Safety:** All data must be validated against TypeScript interfaces -- **Performance:** Use specific node subscriptions instead of full controller subscriptions -- **Memory Management:** Proper cleanup of observers, listeners, and subscriptions - -### **Firebase Schema Requirements:** -- **Controller Structure:** Must match the exact structure defined in `types.ts` -- **Key Format:** Queue items must use sequential numerical keys -- **Data Types:** All data must conform to TypeScript interfaces -- **Required Fields:** Critical fields must be present for operations to succeed -- **Default Values:** Empty controller must have all required fields with default values - -### **Migration & Compatibility:** -- **Key Migration:** Automatic migration of push ID keys to sequential numerical keys -- **Order Fixing:** Automatic repair of inconsistent queue order values -- **Backward Compatibility:** Support for existing data with inconsistent keys -- **Data Validation:** Runtime validation of data structure integrity +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#firebase-patterns` for React/Ionic implementation +- **iOS:** See `platforms/ios/PRD-ios.md#firebase-patterns` (future) +- **Android:** See `platforms/android/PRD-android.md#firebase-patterns` (future) --- -## 18. Critical Implementation Notes +## 17. Critical Implementation Notes ### **DO NOT CHANGE These Patterns:** -- **Queue Key Management:** Sequential numerical keys (0, 1, 2, etc.) - changing this will break queue functionality -- **Controller Structure:** Exact structure must match `types.ts` - changing will break sync -- **Service Layer Pattern:** All Firebase operations must go through service modules -- **Subscription Pattern:** Real-time updates must use subscribe/unsubscribe pattern -- **Error Handling:** Service-level error handling with console logging must be maintained -- **Type Safety:** All data validation against TypeScript interfaces must be preserved -- **Connection Management:** FirebaseProvider pattern with connection status tracking -- **Cleanup Management:** Proper cleanup of listeners and subscriptions +- **Sequential Queue Keys:** Must always use 0, 1, 2, ... for queue items +- **Firebase Structure:** Controller object structure must remain unchanged +- **Data Validation:** All data must be validated against TypeScript interfaces +- **Business Logic:** Core rules must be enforced client-side +- **Real-time Sync:** All clients must stay synchronized via Firebase -### **Critical Dependencies:** -- **Firebase Config:** Must be properly configured with environment variables -- **TypeScript Interfaces:** Must match exactly with Firebase data structure -- **Redux State:** Must maintain consistency with Firebase data -- **Service Functions:** Must handle all error cases and provide proper cleanup -- **Hook Dependencies:** Must include proper dependency arrays for useEffect hooks - -### **Performance Requirements:** -- **List Pagination:** All lists must use infinite scroll with 20 items per page -- **Memory Management:** Proper cleanup of all listeners and observers -- **Efficient Queries:** Use specific node subscriptions, not full controller subscriptions -- **Optimistic Updates:** UI updates immediately with rollback on error -- **Debounced Operations:** Search and filter operations must be debounced - -### **Error Recovery Patterns:** -- **Graceful Degradation:** App must continue working with cached data during connection issues -- **Retry Logic:** Automatic retry for failed Firebase operations -- **User Feedback:** Clear error messages with recovery options -- **Data Validation:** Runtime validation with fallback values -- **Connection Monitoring:** Real-time connection status with error state management +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#critical-notes` for React/Ionic specifics +- **iOS:** See `platforms/ios/PRD-ios.md#critical-notes` (future) +- **Android:** See `platforms/android/PRD-android.md#critical-notes` (future) --- -## βœ… Summary +## 18. Environment Configuration & .env.local Setup -This PRD serves as the comprehensive source of truth for application logic, Firebase data flow, and feature requirements. -It works alongside `types.ts` and `firebase_schema.json` to inform both human developers and AI tools for accurate implementation. +### **Core Configuration Requirements:** +- **Firebase Configuration:** API keys and project settings +- **Environment Variables:** Platform-specific configuration +- **Development vs Production:** Different settings for different environments -**Key Success Metrics:** -- βœ… **Real-time Sync:** All users see updates within 1 second -- βœ… **Performance:** App loads in under 3 seconds on mobile -- βœ… **Reliability:** 99.9% uptime with graceful error handling -- βœ… **User Experience:** Intuitive interface requiring minimal training -- βœ… **Scalability:** Supports up to 50 concurrent users per session +### **Platform Implementation:** +- **Web:** See `platforms/web/PRD-web.md#environment-setup` for React/Ionic configuration +- **iOS:** See `platforms/ios/PRD-ios.md#environment-setup` (future) +- **Android:** See `platforms/android/PRD-android.md#environment-setup` (future) --- -## 19. Environment Configuration & .env.local Setup - -### **Environment File Structure:** -The application uses Vite's built-in environment variable support with the following file structure: - -``` -project-root/ -β”œβ”€β”€ .env.template # Template file with all required variables -β”œβ”€β”€ .env.local # Local development environment (gitignored) -β”œβ”€β”€ .env.production # Production environment (if needed) -└── .env.staging # Staging environment (if needed) -``` - -### **Required Environment Variables:** - -#### **Firebase Configuration (Required):** -```bash -# Firebase Configuration -VITE_FIREBASE_API_KEY=your-api-key -VITE_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com -VITE_FIREBASE_DATABASE_URL=https://your-project-id-default-rtdb.firebaseio.com -VITE_FIREBASE_PROJECT_ID=your-project-id -VITE_FIREBASE_STORAGE_BUCKET=your-project-id.appspot.com -VITE_FIREBASE_MESSAGING_SENDER_ID=123456789 -VITE_FIREBASE_APP_ID=your-app-id -``` - -#### **App Configuration (Optional with defaults):** -```bash -# App Configuration -VITE_CONTROLLER_NAME=default -VITE_APP_TITLE=SingSalot AI -``` - -### **Environment Variable Usage Pattern:** -- **Vite Prefix:** All environment variables must be prefixed with `VITE_` to be accessible in the client-side code -- **Fallback Values:** All environment variables have fallback values in `src/constants/index.ts` -- **Type Safety:** Environment variables are accessed via `import.meta.env.VITE_*` -- **Build-time Injection:** Variables are injected at build time, not runtime - -### **Configuration Loading Pattern:** -```typescript -// src/constants/index.ts -export const FIREBASE_CONFIG = { - apiKey: import.meta.env.VITE_FIREBASE_API_KEY || 'your-api-key', - authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || 'your-project-id.firebaseapp.com', - databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL || 'https://your-project-id-default-rtdb.firebaseio.com', - projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || 'your-project-id', - storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || 'your-project-id.appspot.com', - messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || '123456789', - appId: import.meta.env.VITE_FIREBASE_APP_ID || 'your-app-id', -}; - -export const CONTROLLER_NAME = import.meta.env.VITE_CONTROLLER_NAME || 'default'; -``` - -### **Setup Instructions:** - -#### **1. Initial Setup:** -```bash -# Copy the template file -cp .env.template .env.local - -# Edit .env.local with your actual Firebase configuration -nano .env.local -``` - -#### **2. Firebase Configuration:** -1. Go to Firebase Console β†’ Project Settings -2. Copy the configuration values from the "General" tab -3. Replace the placeholder values in `.env.local` - -#### **3. Controller Configuration:** -- `VITE_CONTROLLER_NAME`: Set to your desired controller name (default: "default") -- `VITE_APP_TITLE`: Set to your desired app title (default: "SingSalot AI") - -### **Environment-Specific Configurations:** - -#### **Development (.env.local):** -```bash -# Local development with hot reload -VITE_CONTROLLER_NAME=dev-controller -VITE_APP_TITLE=SingSalot AI (Dev) -``` - -#### **Staging (.env.staging):** -```bash -# Pre-production testing -VITE_CONTROLLER_NAME=staging-controller -VITE_APP_TITLE=SingSalot AI (Staging) -``` - -#### **Production (.env.production):** -```bash -# Live production environment -VITE_CONTROLLER_NAME=production-controller -VITE_APP_TITLE=SingSalot AI -``` - -### **Security Considerations:** -- **Client-Side Exposure:** All `VITE_*` variables are exposed in the client bundle -- **Firebase Security:** Firebase API keys are safe to expose in client-side code -- **Database Rules:** Security is enforced through Firebase Realtime Database Rules -- **Environment Isolation:** Use different Firebase projects for different environments - -### **Build Process Integration:** -- **Development:** Uses `.env.local` automatically when running `npm run dev` -- **Production Build:** Uses `.env.production` when running `npm run build` -- **Environment Detection:** Vite automatically detects the correct environment file -- **Build-time Injection:** Variables are replaced at build time, not runtime - -### **Error Handling for Missing Variables:** -- **Fallback Values:** All variables have sensible defaults -- **Console Warnings:** Missing required variables show console warnings -- **Graceful Degradation:** App continues to work with fallback values -- **Development Feedback:** Clear error messages for missing configuration - -### **Environment Variable Validation:** -```typescript -// Validation pattern used in the app -const validateFirebaseConfig = () => { - const requiredVars = [ - 'VITE_FIREBASE_API_KEY', - 'VITE_FIREBASE_AUTH_DOMAIN', - 'VITE_FIREBASE_DATABASE_URL', - 'VITE_FIREBASE_PROJECT_ID' - ]; - - const missing = requiredVars.filter(varName => !import.meta.env[varName]); - - if (missing.length > 0) { - console.warn('Missing Firebase configuration:', missing); - } -}; -``` - -### **Deployment Considerations:** -- **CI/CD Integration:** Environment variables must be set in deployment pipeline -- **Build Commands:** Different build commands for different environments -- **Environment Files:** `.env.local` is gitignored, other files may be committed -- **Secret Management:** Use deployment platform's secret management for production - -### **Troubleshooting:** -- **Variable Not Found:** Ensure variable name starts with `VITE_` -- **Build Issues:** Check that all required variables are set -- **Runtime Errors:** Verify Firebase configuration is correct -- **Environment Detection:** Ensure correct `.env` file is being used - -### **Best Practices:** -- **Template File:** Always maintain `.env.template` with all required variables -- **Documentation:** Document all environment variables and their purposes -- **Validation:** Implement runtime validation for critical configuration -- **Fallbacks:** Provide sensible default values for all variables -- **Security:** Never commit sensitive values to version control - ---- - -## 23. Complete Data Flow Diagrams - -### **Authentication Flow:** -``` -1. User enters Party ID + Name -2. Validate Party ID exists in Firebase -3. If valid: dispatch setAuth action -4. If invalid: show error message "Invalid Party Id. Please check your Party Id and try again." -5. On auth success: initialize Firebase sync -6. Load complete controller object -7. If controller doesn't exist: create empty structure -8. Clean up admin URL parameter if present -``` - -### **Queue Operations Flow:** -``` -Add to Queue: -1. User clicks "Add to Queue" on song -2. Validate controller name and current singer exist -3. Calculate next order: Math.max(existingOrders) + 1 -4. Create queue item with sequential key -5. Call queueService.addToQueue() -6. Firebase updates in real-time -7. All clients receive updated queue -8. Show success toast - -Remove from Queue: -1. User clicks remove (admin only, when not playing) -2. Validate admin permissions and playback state -3. Call queueService.removeFromQueue() -4. Firebase removes item -5. All clients receive updated queue -6. Show success toast - -Reorder Queue: -1. Admin clicks reorder buttons -2. Validate admin permissions and playback state -3. Calculate new order values for affected items -4. Update all affected items atomically with Promise.all() -5. Firebase updates in real-time -6. All clients receive updated queue -7. Show success toast -``` - -### **Search Flow:** -``` -1. User types in search input -2. Debounce 300ms before processing -3. If < 2 characters: show all songs (filtered by disabled songs) -4. If >= 2 characters: filter songs by search term -5. Apply multi-word logic (AND for multiple terms, OR for single term) -6. Filter out disabled songs -7. Paginate results (20 items per page) -8. Show results with infinite scroll -9. Reset to page 1 when search term changes -``` - -### **Real-time Sync Flow:** -``` -1. User authenticates successfully -2. FirebaseProvider initializes -3. Subscribe to controller node: `controllers/${controllerName}` -4. On data change: dispatch setController action -5. Redux updates state -6. Components re-render with new data -7. On unmount: cleanup Firebase listeners -``` - ---- - -## 24. State Management Architecture - -### **Redux State Tree Structure:** -```typescript -{ - auth: { - data: { - authenticated: boolean, - singer: string, - isAdmin: boolean, - controller: string - } | null, - loading: boolean, - error: string | null - }, - controller: { - data: { - favorites: Record, - history: Record, - topPlayed: Record, - newSongs: Record, - disabledSongs: Record, - player: { - queue: Record, - settings: { - autoadvance: boolean, - userpick: boolean - }, - singers: Record, - state: { - state: PlayerState - } - }, - songList: Record, - songs: Record - } | null, - loading: boolean, - error: string | null, - lastUpdated: number | null - } -} -``` - -### **Key Selectors (Memoized):** -```typescript -// Authentication -selectIsAuthenticated: (state) => state.auth.data?.authenticated -selectControllerName: (state) => state.auth.data?.controller -selectCurrentSinger: (state) => state.auth.data?.singer -selectIsAdmin: (state) => state.auth.data?.isAdmin - -// Controller Data -selectController: (state) => state.controller.data -selectSongs: (state) => state.controller.data?.songs -selectQueue: (state) => state.controller.data?.player.queue -selectFavorites: (state) => state.controller.data?.favorites -selectHistory: (state) => state.controller.data?.history -selectTopPlayed: (state) => state.controller.data?.topPlayed -selectNewSongs: (state) => state.controller.data?.newSongs -selectDisabledSongs: (state) => state.controller.data?.disabledSongs -selectSettings: (state) => state.controller.data?.player.settings -selectSingers: (state) => state.controller.data?.player.singers -selectPlayerState: (state) => state.controller.data?.player.state - -// Derived Data -selectSongsArray: createSelector([selectSongs], (songs) => - sortSongsByArtistAndTitle(objectToArray(songs)) -) -selectQueueWithUserInfo: createSelector([selectQueue, selectCurrentSinger], (queue, currentSinger) => - addUserInfoToQueue(queue, currentSinger) -) -selectQueueLength: createSelector([selectQueue], (queue) => - Object.keys(queue || {}).length -) -``` - -### **Action Types:** -```typescript -// Auth Actions -setAuth: Authentication -setLoading: boolean -setError: string -clearError: void -logout: void -updateSinger: string -setAdminStatus: boolean - -// Controller Actions -setController: Controller -updateSongs: Record -updateQueue: Record -updateFavorites: Record -updateHistory: Record -updateTopPlayed: Record -clearError: void -resetController: void -``` - ---- - -## 25. Service Layer API Specifications - -### **Controller Service:** -```typescript -controllerService.getController(controllerName: string): Promise -- Validates: controllerName is non-empty string -- Returns: Complete controller object or null if not exists -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -controllerService.setController(controllerName: string, data: Controller): Promise -- Validates: controllerName and data are provided -- Action: Overwrites entire controller object -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -controllerService.updateController(controllerName: string, updates: Partial): Promise -- Validates: controllerName and updates are provided -- Action: Updates specific parts of controller -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -controllerService.subscribeToController(controllerName: string, callback: (data: Controller | null) => void): () => void -- Validates: controllerName and callback are provided -- Action: Sets up real-time listener -- Returns: Unsubscribe function -- Throws: Error if listener setup fails -- Timeout: None (Firebase handles) -``` - -### **Queue Service:** -```typescript -queueService.addToQueue(controllerName: string, queueItem: Omit): Promise<{ key: string }> -- Validates: controllerName, queueItem with required fields -- Calculates: Next sequential key (Math.max(existingKeys) + 1) -- Action: Adds item to queue with sequential key -- Returns: { key: string } with the new key -- Throws: Error if validation fails or Firebase operation fails -- Timeout: None (Firebase handles) - -queueService.removeFromQueue(controllerName: string, queueItemKey: string): Promise -- Validates: controllerName and queueItemKey are provided -- Action: Removes item from queue -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -queueService.updateQueueItem(controllerName: string, queueItemKey: string, updates: Partial): Promise -- Validates: controllerName, queueItemKey, and updates are provided -- Action: Updates specific fields of queue item -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -queueService.cleanupQueueKeys(controllerName: string): Promise -- Validates: controllerName is provided -- Action: Migrates push ID keys to sequential numerical keys -- Logic: Find non-numerical keys, assign sequential keys, update atomically -- Returns: void -- Throws: Error if migration fails -- Timeout: None (Firebase handles) - -queueService.subscribeToQueue(controllerName: string, callback: (data: Record) => void): () => void -- Validates: controllerName and callback are provided -- Action: Sets up real-time listener for queue changes -- Returns: Unsubscribe function -- Throws: Error if listener setup fails -- Timeout: None (Firebase handles) -``` - -### **Disabled Songs Service:** -```typescript -disabledSongsService.generateSongKey(songPath: string): string -- Validates: songPath is non-empty string -- Algorithm: Simple hash function ((hash << 5) - hash) + charCodeAt(i) -- Returns: Base36 string for Firebase-safe key -- Throws: None (pure function) - -disabledSongsService.addDisabledSong(controllerName: string, song: Song): Promise -- Validates: controllerName, song.path, song.artist, song.title -- Action: Adds song to disabled list with hash key -- Returns: void -- Throws: Error if validation fails or Firebase operation fails -- Timeout: 10 seconds - -disabledSongsService.removeDisabledSong(controllerName: string, songPath: string): Promise -- Validates: controllerName and songPath are provided -- Action: Removes song from disabled list -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: 10 seconds - -disabledSongsService.isSongDisabled(controllerName: string, songPath: string): Promise -- Validates: controllerName and songPath are provided -- Action: Checks if song is in disabled list -- Returns: boolean -- Throws: Error if Firebase operation fails -- Timeout: 10 seconds - -disabledSongsService.getDisabledSongs(controllerName: string): Promise> -- Validates: controllerName is provided -- Action: Gets all disabled songs -- Returns: Record of disabled songs -- Throws: Error if Firebase operation fails -- Timeout: 10 seconds - -disabledSongsService.getDisabledSongPaths(controllerName: string): Promise> -- Validates: controllerName is provided -- Action: Gets disabled song paths as Set for fast lookup -- Returns: Set of disabled song paths -- Throws: Error if Firebase operation fails -- Timeout: 10 seconds - -disabledSongsService.subscribeToDisabledSongs(controllerName: string, callback: (data: Record) => void): () => void -- Validates: controllerName and callback are provided -- Action: Sets up real-time listener for disabled songs -- Returns: Unsubscribe function -- Throws: Error if listener setup fails -- Timeout: None (Firebase handles) -``` - -### **Singer Service:** -```typescript -singerService.addSinger(controllerName: string, singerName: string): Promise<{ key: string }> -- Validates: controllerName and singerName are non-empty, trimmed -- Checks: Case-insensitive duplicate prevention -- Action: Adds singer with current timestamp -- Returns: { key: string } with Firebase push key -- Throws: Error if validation fails, duplicate exists, or Firebase operation fails -- Timeout: None (Firebase handles) - -singerService.removeSinger(controllerName: string, singerName: string): Promise -- Validates: controllerName and singerName are provided -- Action: Removes singer and their queue items -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -singerService.subscribeToSingers(controllerName: string, callback: (data: Record) => void): () => void -- Validates: controllerName and callback are provided -- Action: Sets up real-time listener for singers -- Returns: Unsubscribe function -- Throws: Error if listener setup fails -- Timeout: None (Firebase handles) -``` - -### **Player Service:** -```typescript -playerService.updatePlayerStateValue(controllerName: string, state: PlayerState): Promise -- Validates: controllerName and state are provided -- Action: Updates player state -- Returns: void -- Throws: Error if Firebase operation fails -- Timeout: None (Firebase handles) - -playerService.subscribeToPlayerState(controllerName: string, callback: (data: Player) => void): () => void -- Validates: controllerName and callback are provided -- Action: Sets up real-time listener for player state -- Returns: Unsubscribe function -- Throws: Error if listener setup fails -- Timeout: None (Firebase handles) -``` - ---- - -## 26. Component Architecture Specifications - -### **SongItem Component:** -```typescript -interface SongItemProps { - song: Song; - context: 'search' | 'queue' | 'history' | 'favorites' | 'topPlayed' | 'newSongs'; - onAddToQueue?: (song: Song) => void; - onRemoveFromQueue?: (queueItem: QueueItem) => void; - onToggleFavorite?: (song: Song) => void; - onDelete?: (song: Song) => void; - onSelectSinger?: (song: Song) => void; - isAdmin?: boolean; - className?: string; - showActions?: boolean; - showPath?: boolean; - showCount?: boolean; - showInfoButton?: boolean; - showAddButton?: boolean; - showRemoveButton?: boolean; - showDeleteButton?: boolean; - showFavoriteButton?: boolean; -} - -Event Flow: -1. User clicks action button -2. Component calls prop function (e.g., onAddToQueue) -3. Hook handles business logic (useSongOperations) -4. Service updates Firebase (queueService.addToQueue) -5. Real-time listener updates Redux -6. Component re-renders with new data -7. Toast notification shows success/error -``` - -### **InfiniteScrollList Component:** -```typescript -interface InfiniteScrollListProps { - items: any[]; - context: 'search' | 'queue' | 'history' | 'favorites' | 'topPlayed' | 'newSongs'; - isLoading: boolean; - hasMore: boolean; - onLoadMore: () => void; - renderItem: (item: any, index: number) => React.ReactNode; - className?: string; - debug?: boolean; -} - -Behavior: -1. Renders items with renderItem function -2. Shows loading spinner when isLoading && items.length === 0 -3. Shows empty state when items.length === 0 && !isLoading -4. Shows load more trigger when hasMore && items.length > 0 -5. Uses Intersection Observer to detect when user scrolls to bottom 10% -6. Calls onLoadMore when trigger is visible -7. Cleans up observer on unmount -``` - -### **ActionButton Component:** -```typescript -interface ActionButtonProps { - onClick: () => void; - children: React.ReactNode; - variant?: 'primary' | 'secondary' | 'danger'; - size?: 'sm' | 'md' | 'lg'; - disabled?: boolean; - icon?: string; - className?: string; -} - -Behavior: -1. Renders button with variant styling -2. Shows icon if provided -3. Disables button when disabled prop is true -4. Calls onClick when clicked -5. Supports different sizes and variants -``` - -### **PlayerControls Component:** -```typescript -interface PlayerControlsProps { - className?: string; - variant?: 'light' | 'dark'; -} - -Behavior: -1. Only renders for admin users (selectIsAdmin) -2. Shows current player state with color-coded badge -3. Play button: disabled when queue is empty -4. Pause button: only shown when playing -5. Stop button: only shown when playing or paused -6. Calls playerService.updatePlayerStateValue on button clicks -7. Shows success/error toasts for feedback -``` - -### **Component Hierarchy:** -``` -App -β”œβ”€β”€ ErrorBoundary -β”œβ”€β”€ FirebaseProvider -β”œβ”€β”€ Router -β”œβ”€β”€ AuthInitializer -β”œβ”€β”€ Layout -β”‚ β”œβ”€β”€ Navigation -β”‚ └── Routes -β”‚ β”œβ”€β”€ Search -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ Queue -β”‚ β”‚ β”œβ”€β”€ PlayerControls -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ Favorites -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ History -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ TopPlayed -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ NewSongs -β”‚ β”‚ └── InfiniteScrollList -β”‚ β”‚ └── SongItem -β”‚ β”œβ”€β”€ Artists -β”‚ β”‚ └── ArtistModal -β”‚ β”œβ”€β”€ SongLists -β”‚ β”‚ └── SongListModal -β”‚ β”œβ”€β”€ Singers -β”‚ └── Settings -└── Toast (global) -``` - ---- - -## 27. Error Handling Matrix - -### **Network Errors:** -``` -Firebase Connection Lost: -- Detection: onValue error callback -- Action: Show connection status indicator -- Recovery: Automatic retry with exponential backoff -- User Feedback: "Connection lost. Retrying..." - -Firebase Timeout (10s): -- Detection: Promise.race with timeout -- Action: Show error toast -- Recovery: Allow manual retry -- User Feedback: "Operation timed out. Please try again." - -Network Unavailable: -- Detection: navigator.onLine or fetch error -- Action: Show offline indicator -- Recovery: Queue operations for when online -- User Feedback: "You're offline. Changes will sync when connected." -``` - -### **Validation Errors:** -``` -Party ID Invalid: -- Detection: Firebase get() returns null -- Action: Show error message -- Recovery: Allow user to retry -- User Feedback: "Invalid Party Id. Please check your Party Id and try again." - -Singer Name Empty: -- Detection: singerName.trim().length === 0 -- Action: Highlight input field -- Recovery: Prevent form submission -- User Feedback: "Singer name cannot be empty" - -Singer Already Exists: -- Detection: Case-insensitive name comparison -- Action: Show error toast -- Recovery: Allow user to choose different name -- User Feedback: "Singer already exists" - -Required Fields Missing: -- Detection: Check for undefined/null values -- Action: Highlight missing fields -- Recovery: Prevent operation -- User Feedback: "Please fill in all required fields" -``` - -### **Permission Errors:** -``` -Admin Action by Non-Admin: -- Detection: selectIsAdmin === false -- Action: Hide admin-only UI elements -- Recovery: Show permission error -- User Feedback: "Only admins can perform this action" - -Delete During Playback: -- Detection: playerState.state === 'playing' -- Action: Disable delete buttons -- Recovery: Allow delete when stopped/paused -- User Feedback: "Cannot delete while playing" -``` - -### **Concurrent Conflicts:** -``` -Queue Reorder Conflict: -- Detection: Order values don't match expected sequence -- Action: Auto-fix order values -- Recovery: Update all items with sequential order -- User Feedback: "Queue order has been corrected" - -Singer Add Conflict: -- Detection: Duplicate name (case-insensitive) -- Action: Prevent addition -- Recovery: Show error message -- User Feedback: "Singer already exists" - -Settings Change Conflict: -- Detection: Multiple users changing settings simultaneously -- Action: Last write wins -- Recovery: Show conflict notification -- User Feedback: "Settings updated by another user" -``` - -### **Data Corruption:** -``` -Invalid Queue Order: -- Detection: Order values not sequential (1, 2, 3, ...) -- Action: Auto-fix order values -- Recovery: Update all items with correct order -- User Feedback: "Queue order has been corrected" - -Missing Required Fields: -- Detection: Required fields are undefined/null -- Action: Use default values or skip item -- Recovery: Log error and continue -- User Feedback: "Some data could not be loaded" - -Invalid Firebase Keys: -- Detection: Non-numerical keys in queue -- Action: Run cleanupQueueKeys() -- Recovery: Migrate to sequential keys -- User Feedback: "Queue has been updated" -``` - ---- - -## 28. Performance Specifications - -### **Memoization Rules:** -```typescript -// Redux Selectors (Always Memoize) -selectSongsArray: createSelector([selectSongs], (songs) => - sortSongsByArtistAndTitle(objectToArray(songs)) -) - -selectQueueWithUserInfo: createSelector([selectQueue, selectCurrentSinger], (queue, currentSinger) => - addUserInfoToQueue(queue, currentSinger) -) - -// Component Props (Memoize Expensive Calculations) -const filteredSongs = useMemo(() => - filterSongs(allSongs, searchTerm, disabledSongPaths), - [allSongs, searchTerm, disabledSongPaths] -) - -// Event Handlers (Use useCallback for Async Operations) -const handleAddToQueue = useCallback(async (song: Song) => { - await addToQueue(song); -}, [addToQueue]); - -const handleRemoveFromQueue = useCallback(async (queueItem: QueueItem) => { - await removeFromQueue(queueItem); -}, [removeFromQueue]); -``` - -### **Bundle Splitting Strategy:** -```typescript -// Route-based Splitting -const Search = lazy(() => import('./features/Search/Search')); -const Queue = lazy(() => import('./features/Queue/Queue')); -const Favorites = lazy(() => import('./features/Favorites/Favorites')); -const History = lazy(() => import('./features/History/History')); -const TopPlayed = lazy(() => import('./features/TopPlayed/Top100')); -const NewSongs = lazy(() => import('./features/NewSongs/NewSongs')); -const Artists = lazy(() => import('./features/Artists/Artists')); -const SongLists = lazy(() => import('./features/SongLists/SongLists')); -const Singers = lazy(() => import('./features/Singers/Singers')); -const Settings = lazy(() => import('./features/Settings/Settings')); - -// Component-based Splitting -const ArtistModal = lazy(() => import('./components/common/ArtistModal')); -const SongListModal = lazy(() => import('./components/common/SongListModal')); - -// Vendor Splitting -// Third-party libraries (Ionic, Firebase) in separate chunks -``` - -### **Virtual Scrolling (Future Implementation):** -```typescript -// For lists with 1000+ items -interface VirtualScrollConfig { - itemHeight: number; - overscan: number; - containerHeight: number; -} - -// Only render visible items + buffer -const visibleItems = items.slice(startIndex, endIndex + overscan); -``` - -### **Image Optimization:** -```typescript -// Lazy load images -const LazyImage = ({ src, alt, ...props }) => { - const [isLoaded, setIsLoaded] = useState(false); - const [isInView, setIsInView] = useState(false); - - useEffect(() => { - if (isInView) { - const img = new Image(); - img.onload = () => setIsLoaded(true); - img.src = src; - } - }, [isInView, src]); - - return ( -
- {!isLoaded && } - {isInView && {alt}} -
- ); -}; -``` - -### **Firebase Optimization:** -```typescript -// Specific node subscriptions instead of full controller -const queueRef = ref(database, `controllers/${controllerName}/player/queue`); -const favoritesRef = ref(database, `controllers/${controllerName}/favorites`); - -// Batch operations for multiple updates -const updates = {}; -updates[`controllers/${controllerName}/player/queue/${key1}`] = item1; -updates[`controllers/${controllerName}/player/queue/${key2}`] = item2; -await update(ref(database), updates); -``` - -### **Memory Management:** -```typescript -// Cleanup listeners on unmount -useEffect(() => { - const unsubscribe = subscribeToQueue(controllerName, callback); - return () => unsubscribe(); -}, [controllerName]); - -// Cleanup observers -useEffect(() => { - const observer = new IntersectionObserver(callback, options); - observer.observe(element); - return () => observer.disconnect(); -}, []); -``` - ---- - -## 29. Implementation Guide for New Projects +## 19. Implementation Guide for New Projects ### **Quick Start Questions for Implementation:** -When starting a new implementation, ask these questions to determine the approach: +#### **1. Platform Choice:** +- **What platform** are you building for? (Web, iOS, Android, Desktop) +- **What framework** will you use? (React, Vue, SwiftUI, Jetpack Compose, etc.) +- **What UI library** will you use? (Ionic, Material-UI, native components, etc.) -#### **1. Platform Target:** -- **Web:** Browser-based application -- **iOS:** Native iOS app (Swift/SwiftUI) -- **Android:** Native Android app (Kotlin/Jetpack Compose) -- **Cross-platform:** Single codebase for multiple platforms (Flutter, React Native) +#### **2. State Management:** +- **How will you manage state?** (Redux, Context API, Zustand, native state management) +- **How will you handle real-time updates?** (Firebase listeners, WebSockets, etc.) -#### **2. Framework Choice (Based on Platform):** -- **Web:** React, Vue, Svelte, Angular -- **iOS:** SwiftUI, UIKit -- **Android:** Jetpack Compose, Views -- **Cross-platform:** Flutter, React Native +#### **3. Data Flow:** +- **How will you structure your data layer?** (Services, repositories, etc.) +- **How will you handle Firebase integration?** (Direct SDK, abstraction layer, etc.) -#### **3. State Management:** -- **Centralized:** Redux, Zustand, Pinia, Jotai -- **Local:** React Context, Vue Composition API -- **Platform-specific:** SwiftUI @State, Jetpack Compose StateFlow +#### **4. UI/UX:** +- **How will you implement the UI?** (Components, layouts, navigation) +- **How will you handle responsive design?** (Mobile-first, adaptive layouts, etc.) -#### **4. UI Framework:** -- **Web:** Ionic, Chakra UI, Material UI, Ant Design -- **Native:** Platform-specific components -- **Cross-platform:** Framework-specific UI libraries +#### **5. Performance:** +- **How will you optimize performance?** (Memoization, lazy loading, etc.) +- **How will you handle large datasets?** (Pagination, virtualization, etc.) -#### **5. Backend/Data:** -- **Firebase:** Realtime Database, Firestore -- **Supabase:** PostgreSQL with real-time -- **AWS:** AppSync, DynamoDB -- **Custom:** REST API with WebSockets +#### **6. Testing:** +- **How will you test your implementation?** (Unit tests, integration tests, etc.) +- **How will you validate business logic?** (Test coverage, validation tests, etc.) -#### **6. Build Tool:** -- **Web:** Vite, Webpack, Parcel -- **iOS:** Xcode -- **Android:** Android Studio -- **Cross-platform:** Framework-specific tools - -#### **7. Styling:** -- **Web:** Tailwind CSS, CSS Modules, Styled Components -- **Native:** Platform-specific styling -- **Cross-platform:** Framework-specific styling +#### **7. Deployment:** +- **How will you deploy your app?** (Build tools, hosting, app stores, etc.) +- **How will you manage environments?** (Development, staging, production) ### **Implementation Checklist:** -#### **Phase 1: Project Setup** -- [ ] Create project with chosen framework/tools -- [ ] Set up Firebase/backend configuration -- [ ] Configure state management -- [ ] Set up routing/navigation -- [ ] Configure build tools and deployment +#### **Phase 1: Foundation** +- [ ] Set up project structure and dependencies +- [ ] Configure Firebase project and environment +- [ ] Implement data models and TypeScript interfaces +- [ ] Set up state management architecture +- [ ] Create basic UI components and layout -#### **Phase 2: Core Architecture** -- [ ] Implement service layer (all Firebase operations) -- [ ] Set up state management (Redux slices/selectors) -- [ ] Create base components (SongItem, ActionButton, etc.) -- [ ] Implement authentication flow -- [ ] Set up real-time sync +#### **Phase 2: Core Features** +- [ ] Implement authentication and user management +- [ ] Create Firebase service layer +- [ ] Build queue management functionality +- [ ] Implement search and song browsing +- [ ] Add favorites and history tracking -#### **Phase 3: Feature Implementation** -- [ ] Search functionality with disabled songs filtering -- [ ] Queue management with sequential keys -- [ ] Favorites system -- [ ] History tracking -- [ ] Top played with cloud functions -- [ ] Singer management -- [ ] Player controls -- [ ] Settings and disabled songs -- [ ] Artists and song lists +#### **Phase 3: Advanced Features** +- [ ] Implement real-time synchronization +- [ ] Add admin controls and permissions +- [ ] Build singer management system +- [ ] Create settings and configuration +- [ ] Implement error handling and resilience -#### **Phase 4: Error Handling & Performance** -- [ ] Implement error handling matrix +#### **Phase 4: Polish & Optimization** - [ ] Add performance optimizations -- [ ] Set up bundle splitting -- [ ] Add loading states and empty states -- [ ] Implement infinite scroll +- [ ] Implement comprehensive testing +- [ ] Add accessibility features +- [ ] Optimize for different screen sizes +- [ ] Prepare for deployment -#### **Phase 5: Testing & Polish** -- [ ] Test all business logic -- [ ] Verify real-time sync -- [ ] Test error scenarios -- [ ] Performance testing -- [ ] UI/UX polish +#### **Phase 5: Deployment & Launch** +- [ ] Set up production environment +- [ ] Configure build and deployment pipeline +- [ ] Perform final testing and validation +- [ ] Deploy to target platform +- [ ] Monitor and maintain -### **Key Implementation Notes:** +### **Critical Success Factors:** +- **Follow the Firebase structure** exactly as defined +- **Implement all business logic** client-side +- **Maintain real-time synchronization** across all clients +- **Validate all data** against TypeScript interfaces +- **Test thoroughly** before deployment -#### **Must Preserve (Regardless of Framework):** -- **Business Logic:** All validation rules, calculations, and data flows -- **Service Layer:** All Firebase operations with exact signatures -- **State Structure:** Same data organization and relationships -- **Error Handling:** All error scenarios and recovery strategies -- **Performance:** Memoization, bundle splitting, and optimization patterns - -#### **Can Replace (Framework-Specific):** -- **UI Components:** Replace with framework-equivalent components -- **State Management Library:** Replace Redux with framework-appropriate solution -- **Styling:** Replace Tailwind with framework-appropriate styling -- **Build Tools:** Replace Vite with framework-appropriate build system - -#### **Critical Success Factors:** -- **Follow data flow diagrams exactly** -- **Implement all service functions with exact signatures** -- **Maintain same state structure and relationships** -- **Handle all error scenarios from the matrix** -- **Preserve all business logic and validation rules** +### **Platform-Specific Guidance:** +- **Web:** See `platforms/web/PRD-web.md` for React/Ionic implementation details +- **iOS:** See `platforms/ios/PRD-ios.md` for Swift/SwiftUI implementation (future) +- **Android:** See `platforms/android/PRD-android.md` for Kotlin/Jetpack Compose implementation (future) --- -## 20. Third-Party UI Library - Ionic React - -### **Current UI Implementation:** -The application currently uses **Tailwind CSS** for styling with custom components. While functional, this approach requires significant custom development for responsive design and native platform feel. - -### **Recommended Solution: Ionic React** - -For a **mobile-first app that works on web**, **Ionic React** is the single best choice because it provides native platform feel across all devices while maintaining web compatibility. - -#### **Installation:** -```bash -npm install @ionic/react @ionic/core -``` - -#### **Why Ionic React:** -- **Mobile-First:** Designed specifically for mobile experiences -- **Native Feel:** Mimics iOS and Android native components automatically -- **Web Compatible:** Works perfectly on desktop browsers -- **Touch Optimized:** Built-in touch interactions and gestures -- **Responsive:** Automatic responsive design without custom CSS -- **Accessibility:** Excellent accessibility support out of the box -- **Performance:** Optimized for mobile performance -- **Simple:** One library handles everything - no complex configuration - -#### **Integration Pattern:** -```typescript -// src/components/common/IonicButton.tsx -import { IonButton, IonIcon } from '@ionic/react'; -import { add, heart, play } from 'ionicons/icons'; - -export const ActionButton: React.FC = ({ - onClick, - children, - variant = 'primary', - icon, - disabled = false -}) => { - const getVariant = () => { - switch (variant) { - case 'primary': return 'primary'; - case 'secondary': return 'medium'; - case 'danger': return 'danger'; - default: return 'primary'; - } - }; - - return ( - - {icon && } - {children} - - ); -}; -``` - -#### **Responsive Design (Automatic):** -```typescript -// Ionic handles responsive design automatically -export const SongList: React.FC = () => { - return ( - - {songs.map(song => ( - - -

{song.title}

-

{song.artist}

-
- - - -
- ))} -
- ); -}; -``` - -#### **Navigation (Mobile-First):** -```typescript -// Ionic provides mobile-optimized navigation -export const AppNavigation: React.FC = () => { - return ( - - - - - Queue - - - - Search - - - - Favorites - - - - ); -}; -``` - -#### **Touch Interactions (Built-in):** -```typescript -// Ionic provides touch-optimized interactions automatically -export const SwipeableSongItem: React.FC = ({ - song, - onDelete -}) => { - return ( - - - -

{song.title}

-

{song.artist}

-
-
- - onDelete(song.id)}> - - - -
- ); -}; -``` - -### **Migration Strategy (Simple):** - -#### **Step 1: Install and Setup (1 day)** -```bash -npm install @ionic/react @ionic/core -``` - -Add to `src/main.tsx`: -```typescript -import { setupIonicReact } from '@ionic/react'; - -setupIonicReact(); -``` - -#### **Step 2: Replace Core Components (3-4 days)** -- Replace `ActionButton` with `IonButton` -- Replace custom lists with `IonList` and `IonItem` -- Replace modals with `IonModal` -- Replace toasts with `IonToast` - -#### **Step 3: Update Navigation (1 day)** -- Replace custom navigation with `IonTabs` or `IonMenu` -- Mobile gets bottom tabs, desktop gets side menu automatically - -#### **Step 4: Add Touch Features (1 day)** -- Add swipe-to-delete with `IonItemSliding` -- Add pull-to-refresh with `IonRefresher` -- Add infinite scroll with `IonInfiniteScroll` - -### **Benefits Over Current Approach:** - -#### **Before (Tailwind CSS):** -- ❌ Custom responsive CSS for every component -- ❌ Manual touch interaction implementation -- ❌ Custom mobile navigation -- ❌ Manual accessibility features -- ❌ Complex responsive breakpoints - -#### **After (Ionic React):** -- βœ… Automatic responsive design -- βœ… Built-in touch interactions -- βœ… Mobile-optimized navigation -- βœ… Accessibility built-in -- βœ… Native platform feel -- βœ… Works on all devices automatically - -### **Performance:** -- **Bundle Size:** ~50KB gzipped (minimal overhead) -- **Mobile Performance:** Optimized for mobile devices -- **Web Performance:** Works great on desktop browsers -- **Loading:** Fast initial load with lazy loading - -### **Accessibility:** -- **Screen Readers:** Full support out of the box -- **Keyboard Navigation:** Complete keyboard support -- **Touch Targets:** Proper 44px minimum touch targets -- **WCAG Compliance:** Built-in accessibility standards - -### **Implementation Timeline:** -- **Day 1:** Install and basic setup -- **Days 2-5:** Replace core components -- **Day 6:** Update navigation -- **Day 7:** Add touch features and testing - -### **Success Metrics:** -- **Mobile Performance:** 90+ Lighthouse score -- **Touch Responsiveness:** <100ms response time -- **Accessibility:** WCAG 2.1 AA compliance -- **User Experience:** Native app feel on mobile -- **Web Compatibility:** Perfect desktop experience - -### **Why Not Other Libraries:** -- **Chakra UI:** Great for web, but requires custom mobile optimization -- **Material-UI:** Enterprise-focused, overkill for this app -- **Custom Tailwind:** Too much work for responsive design and touch interactions - -### **Simple Decision:** -**Use Ionic React** - it's the only library that gives you: -1. Mobile-first design automatically -2. Native platform feel -3. Perfect web compatibility -4. Built-in touch interactions -5. Zero configuration responsive design - -No complex choices, no multiple libraries, no over-engineering. Just one library that does everything you need for a mobile-first karaoke app. - ---- - -## 21. Design Assets & Visual Reference - -### **Design Assets Location:** -The `/docs/design/` folder contains comprehensive UI/UX mockups and visual references for different platforms and features. - -### **Current Web Design Assets:** -Located in `/docs/design/web/` with 30+ mockups covering all features: - -#### **Core Navigation & Layout:** -- `00-web-layout.JPG` - Overall web layout structure -- `01-Login.png` - Login screen design -- `02-menu.jpeg`, `02a-menu.jpeg`, `02b-menu.png`, `02c-menu.jpeg` - Navigation menu variations - -#### **Queue Management:** -- `02-queue.png` - Main queue view -- `02-queue-delete.png` - Queue with delete functionality -- `02-queue-drag.png` - Queue reordering with drag and drop -- `02-queue-sorting.png` - Queue sorting interface - -#### **Search & Discovery:** -- `04-search.png` - Main search interface -- `04-search typing .png` - Search with typing interaction -- `04-search-song info.png` - Search results with song information - -#### **User Management:** -- `05-singers.png` - Singer list view -- `05-singers add.png` - Singer management interface - -#### **Content Browsing:** -- `06-artists .png` - Artist browse interface -- `06-artists (not admin).png` - Non-admin artist view -- `06-artists search.png` - Artist search functionality -- `06-artists songs.png` - Artist songs list - -#### **User Features:** -- `07-favorites.png` - Favorites management -- `08-history.png` - Play history view -- `09-songs list.png` - Main song lists view -- `09-song lists - songs.png` - Song lists with song details -- `09- song lists songs expand.png` - Song lists with expandable sections - -#### **Admin Features:** -- `10-Settings.png` - Settings interface -- `11-top 100.png` - Top played songs -- `12-favorites .png` - Favorites view -- `12-favorite lists.png` - Favorite lists management - -#### **Menu States:** -- `03-menu.png` - General menu layout -- `03-menu current page and non-admin.png` - Navigation with current page indicators -- `03-menu playing (admin).png` - Admin view during playback - -### **Future Platform Design Structure:** -``` -design/ -β”œβ”€β”€ web/ # Current web mockups (30+ files) -β”œβ”€β”€ ios/ # Future iOS designs (SwiftUI/UIKit) -β”œβ”€β”€ android/ # Future Android designs (Jetpack Compose/Views) -β”œβ”€β”€ tablet/ # Future tablet designs (iPad/Android tablets) -└── desktop/ # Future desktop designs (Windows/macOS) -``` - -### **Design Asset Guidelines:** -- **Reference during implementation** for visual accuracy -- **Understand UX patterns** and interaction flows -- **Guide UI component design** and layout decisions -- **Ensure consistency** across different implementations -- **Validate feature completeness** against visual requirements - -### **Important Note About Current Web Mockups:** -The web mockups were created using an **older version of Ionic** and may not reflect the current Ionic React component API or styling. However, they serve as valuable reference for: - -#### **Layout Intent:** -- **Overall Structure:** How the app should be organized -- **Navigation Flow:** User journey through different screens -- **Component Placement:** Where buttons, lists, and controls should be positioned -- **Information Hierarchy:** How data should be prioritized and displayed - -#### **User Experience Goals:** -- **Mobile-First Design:** Touch-friendly interface elements -- **Intuitive Navigation:** Clear paths between features -- **Context-Aware Actions:** Different actions based on user role and context -- **Real-time Updates:** Visual indicators for live data changes - -### **Implementation Considerations:** - -#### **Modern Ionic React vs Mockups:** -```typescript -// Mockup shows older Ionic syntax - - Add to Queue - - -// Modern Ionic React syntax (current recommendation) - - - Add to Queue - -``` - -#### **Component Mapping:** -| Mockup Component | Modern Ionic React Component | -|------------------|------------------------------| -| Old Button | `IonButton` with `fill` prop | -| Old List | `IonList` with `IonItem` | -| Old Modal | `IonModal` with `IonHeader` | -| Old Navigation | `IonTabs` or `IonMenu` | -| Old Toast | `IonToast` with `position` prop | - -#### **Styling Updates:** -- **Colors:** Modern Ionic uses semantic color names -- **Spacing:** Updated spacing system for better mobile experience -- **Typography:** Improved font scaling for accessibility -- **Touch Targets:** Enhanced minimum touch target sizes - -### **Using Mockups for Implementation:** - -#### **1. Layout Reference:** -- Use mockups to understand the intended layout structure -- Follow the visual hierarchy shown in the designs -- Maintain the component relationships and positioning - -#### **2. Feature Requirements:** -- Identify required functionality from mockups -- Understand user interaction patterns -- Note admin vs user permission differences - -#### **3. User Flow Validation:** -- Verify navigation paths match mockup flow -- Ensure all screens are implemented -- Confirm user roles and permissions are correctly applied - -#### **4. Modern Implementation:** -- Use current Ionic React components and syntax -- Apply modern responsive design principles -- Implement current accessibility standards -- Follow current performance best practices - -### **Migration from Mockups to Modern Ionic:** - -#### **Step 1: Component Analysis** -- Review each mockup for required components -- Map to current Ionic React component library -- Identify any custom components needed - -#### **Step 2: Layout Implementation** -- Implement responsive layouts using modern Ionic grid -- Use current Ionic spacing and sizing system -- Apply modern touch interaction patterns - -#### **Step 3: Feature Implementation** -- Build features using current Ionic React APIs -- Implement modern state management patterns -- Apply current performance optimization techniques - -#### **Step 4: Testing and Refinement** -- Test on actual mobile devices -- Verify touch interactions work correctly -- Ensure accessibility compliance -- Optimize for performance - -### **Key Differences to Note:** - -#### **Navigation:** -- **Mockups:** May show older navigation patterns -- **Modern:** Use `IonTabs` for bottom navigation on mobile -- **Modern:** Use `IonMenu` for side navigation on desktop - -#### **Lists:** -- **Mockups:** May show older list styling -- **Modern:** Use `IonList` with `IonItem` for better performance -- **Modern:** Implement `IonItemSliding` for swipe actions - -#### **Forms:** -- **Mockups:** May show older form components -- **Modern:** Use `IonInput`, `IonSelect`, etc. for better UX -- **Modern:** Implement proper form validation - -#### **Modals:** -- **Mockups:** May show older modal patterns -- **Modern:** Use `IonModal` with proper backdrop handling -- **Modern:** Implement proper focus management - -### **Recommendation:** -1. **Use mockups as layout and UX reference** -2. **Implement using current Ionic React components** -3. **Follow modern responsive design principles** -4. **Test on actual devices for touch interactions** -5. **Ensure accessibility and performance compliance** - -The mockups provide excellent guidance for the intended user experience, but the implementation should use current Ionic React best practices and components. - ---- - -## 22. Development Setup & Configuration +_This document contains platform-agnostic business logic and Firebase architecture. For platform-specific implementation details, see the corresponding platform PRD in the `platforms/` folder._ diff --git a/docs/README.md b/docs/README.md index fd838d6..b9202bd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,7 +17,7 @@ These files are intended for: | `PRD.md` | **Complete Product Requirements Document** β€” platform-agnostic business logic, technical specifications, data flows, service APIs, component architecture, error handling, and performance optimizations. **Self-guiding for AI implementation.** | | `types.ts` | Reference TypeScript interfaces used for modeling app objects. **Not imported into app runtime code.** | | `firebase_schema.json` | Example Firebase Realtime Database structure for understanding data relationships and CRUD operations. | -| `design/` | **UI/UX Design Assets** β€” mockups and visual references for different platforms and features. | +| `platforms/web/design/` | **Web UI/UX Design Assets** β€” mockups and visual references for web platform features. | --- @@ -38,7 +38,7 @@ Simply say **"Read this PRD"** in any new chat. The PRD contains: ### **For New Implementations:** 1. **Read the PRD completely** - it contains comprehensive specifications -2. **Review design assets** in `design/` folder for visual reference +2. **Review design assets** in `platforms/web/design/` folder for visual reference 3. **Answer implementation questions** from Section 29 4. **Follow the implementation checklist** for complete build process 5. **Preserve business logic** while adapting UI to chosen framework @@ -48,24 +48,24 @@ Simply say **"Read this PRD"** in any new chat. The PRD contains: ## πŸ“‹ Key Features of the Updated PRD ### **Platform-Agnostic Design:** -- **Core requirements** separated from implementation details -- **Framework-specific sections** clearly marked -- **Migration guidance** for different platforms -- **Toolset rationale** for informed technology choices +- **Core business logic** completely separated from implementation details +- **Firebase architecture** and data models for any platform +- **Cross-platform references** to platform-specific PRDs +- **Universal business rules** that apply to all implementations ### **Complete Technical Specifications:** -- **Data flow diagrams** for all operations -- **State management architecture** with exact structure -- **Service layer APIs** with function signatures -- **Component architecture** with interfaces and behavior -- **Error handling matrix** for all scenarios -- **Performance specifications** with optimization patterns +- **Firebase data structure** and relationships +- **Business logic patterns** and validation rules +- **Real-time synchronization** requirements +- **User role permissions** and access control +- **Error handling scenarios** and recovery patterns +- **Performance requirements** and optimization guidelines ### **Implementation Guide:** -- **7 key questions** to determine platform/framework -- **5-phase implementation checklist** -- **Must preserve vs. can replace** guidelines -- **Critical success factors** for accurate builds +- **Platform selection questions** to determine technology stack +- **5-phase implementation checklist** for complete builds +- **Business logic preservation** guidelines +- **Critical success factors** for accurate implementations ### **Design Assets:** - **Visual mockups** for all major features and screens @@ -110,8 +110,8 @@ Simply say **"Read this PRD"** in any new chat. The PRD contains: ## 🎨 Design Assets Reference -### **Current Design Assets:** -Located in `design/web/` folder with comprehensive mockups for all features: +### **Current Web Design Assets:** +Located in `platforms/web/design/` folder with comprehensive mockups for all features: #### **Core Navigation & Layout:** - `00-web-layout.JPG` - Overall web layout structure @@ -159,12 +159,17 @@ Located in `design/web/` folder with comprehensive mockups for all features: ### **Future Platform Design Structure:** ``` -design/ -β”œβ”€β”€ web/ # Current web mockups -β”œβ”€β”€ ios/ # Future iOS designs -β”œβ”€β”€ android/ # Future Android designs -β”œβ”€β”€ tablet/ # Future tablet designs -└── desktop/ # Future desktop designs +docs/platforms/ +β”œβ”€β”€ web/ +β”‚ └── design/ # Current web mockups +β”œβ”€β”€ ios/ +β”‚ └── design/ # Future iOS designs +β”œβ”€β”€ android/ +β”‚ └── design/ # Future Android designs +β”œβ”€β”€ tablet/ +β”‚ └── design/ # Future tablet designs +└── desktop/ + └── design/ # Future desktop designs ``` ### **Using Design Assets:** diff --git a/docs/platforms/web/PRD-web.md b/docs/platforms/web/PRD-web.md new file mode 100644 index 0000000..93011d9 --- /dev/null +++ b/docs/platforms/web/PRD-web.md @@ -0,0 +1,759 @@ +# Web Platform Implementation Guide + +> **Platform:** Web (React + Ionic + TypeScript) +> **Core Business Logic:** See `../../PRD.md` for platform-agnostic requirements + +This document contains **web-specific implementation details** for the Karaoke App. All business logic, data models, and core requirements are defined in the main PRD. + +--- + +## Quick Reference + +| Section | Purpose | +|---------|---------| +| [UI/UX Behavior](#uiux-behavior) | Web-specific UI patterns and interactions | +| [Component Architecture](#component-architecture) | React/Ionic component structure | +| [State Management](#state-management) | Redux Toolkit implementation | +| [Development Setup](#development-setup) | Web project configuration | +| [Design Assets](#design-assets) | Web-specific visual references | +| [Toolset Choices](#toolset-choices) | Web technology rationale | + +--- + +## UI/UX Behavior + +### **Web-Specific Requirements:** + +#### **Responsive Design:** +- **Mobile-first approach** with touch-friendly interface +- **Progressive Web App (PWA)** capabilities for app-like experience +- **Responsive breakpoints** for tablet and desktop views +- **Touch gestures** for queue reordering and navigation + +#### **Ionic React Components:** +- **IonApp** as root container with proper theming +- **IonRouterOutlet** for navigation between pages +- **IonList** and **IonItem** for song and queue displays +- **IonButton** with proper touch targets (44px minimum) +- **IonSearchbar** for song search with debounced input +- **IonModal** for singer selection and settings +- **IonToast** for user feedback and notifications + +#### **Navigation Patterns:** +- **Tab-based navigation** for main sections (Queue, Search, History, etc.) +- **Stack navigation** for detail views (song info, artist pages) +- **Modal overlays** for quick actions (singer selection, settings) +- **Deep linking** support for direct page access + +#### **Real-time Updates:** +- **Live queue updates** with visual indicators for changes +- **Playback state synchronization** across all connected devices +- **User presence indicators** showing who's currently active +- **Optimistic UI updates** with rollback on errors + +--- + +## Codebase Organization & File Structure + +### **Web Project Structure:** +``` +src/ +β”œβ”€β”€ components/ # Reusable UI components +β”‚ β”œβ”€β”€ Auth/ # Authentication components +β”‚ β”œβ”€β”€ common/ # Shared components (SongItem, ActionButton, etc.) +β”‚ β”œβ”€β”€ Layout/ # Layout and navigation components +β”‚ └── Navigation/ # Navigation components +β”œβ”€β”€ features/ # Feature-specific components +β”‚ β”œβ”€β”€ Artists/ # Artist browsing feature +β”‚ β”œβ”€β”€ Favorites/ # Favorites management +β”‚ β”œβ”€β”€ History/ # Play history +β”‚ β”œβ”€β”€ NewSongs/ # New songs feature +β”‚ β”œβ”€β”€ Queue/ # Queue management +β”‚ β”œβ”€β”€ Search/ # Song search +β”‚ β”œβ”€β”€ Settings/ # Settings and admin features +β”‚ β”œβ”€β”€ Singers/ # Singer management +β”‚ β”œβ”€β”€ SongLists/ # Song lists feature +β”‚ └── TopPlayed/ # Top played songs +β”œβ”€β”€ firebase/ # Firebase configuration and services +β”‚ β”œβ”€β”€ config.ts # Firebase configuration +β”‚ β”œβ”€β”€ services.ts # Firebase service layer +β”‚ └── useFirebase.ts # Firebase hooks +β”œβ”€β”€ hooks/ # Custom React hooks +β”‚ β”œβ”€β”€ useQueue.ts # Queue management hooks +β”‚ β”œβ”€β”€ useSearch.ts # Search functionality hooks +β”‚ β”œβ”€β”€ useFavorites.ts # Favorites management hooks +β”‚ └── ... # Other feature hooks +β”œβ”€β”€ redux/ # State management +β”‚ β”œβ”€β”€ store.ts # Redux store configuration +β”‚ β”œβ”€β”€ slices/ # Redux slices +β”‚ β”œβ”€β”€ selectors.ts # Memoized selectors +β”‚ └── hooks.ts # Redux hooks +β”œβ”€β”€ types/ # TypeScript type definitions +└── utils/ # Utility functions +``` + +### **File Organization Rules:** +| Folder | Purpose | Key Files | Import Pattern | +|--------|---------|-----------|----------------| +| `/components` | Reusable UI components | `SongItem.tsx`, `ActionButton.tsx` | `import { SongItem } from '../components/common'` | +| `/features` | Feature-specific pages | `Queue.tsx`, `Search.tsx` | `import { Queue } from '../features/Queue'` | +| `/firebase` | Firebase integration | `services.ts`, `config.ts` | `import { queueService } from '../firebase/services'` | +| `/hooks` | Custom business logic | `useQueue.ts`, `useSearch.ts` | `import { useQueue } from '../hooks/useQueue'` | +| `/redux` | State management | `controllerSlice.ts`, `authSlice.ts`, `selectors.ts` | `import { useAppDispatch, selectQueue } from '../redux'` | +| `/types` | TypeScript definitions | `index.ts` (extends docs/types.ts) | `import type { Song, QueueItem } from '../types'` | + +### **Import Patterns:** + +#### **1. Redux Imports:** +```typescript +// Always import from the main redux index +import { useAppDispatch, useAppSelector } from '../redux'; +import { selectQueue, selectSongs } from '../redux'; +import { setController, updateQueue } from '../redux'; + +// ❌ Don't import directly from slice files +// ❌ import { selectQueue } from '../redux/controllerSlice'; +// βœ… Always use the main redux index +// βœ… import { selectQueue } from '../redux'; +``` + +#### **2. Firebase Service Imports:** +```typescript +// Import services from the main services file +import { queueService, searchService } from '../firebase/services'; + +// ❌ Don't import directly from individual service files +// ❌ import { addToQueue } from '../firebase/queueService'; +// βœ… Always use the main services file +// βœ… import { queueService } from '../firebase/services'; +``` + +#### **3. Type Imports:** +```typescript +// Always use type imports for TypeScript interfaces +import type { Song, QueueItem, Singer } from '../types'; + +// ❌ Don't import types from individual files +// ❌ import { Song } from '../types/Song'; +// βœ… Always use the main types index +// βœ… import type { Song } from '../types'; +``` + +#### **4. Hook Imports:** +```typescript +// Import hooks from their specific files +import { useQueue } from '../hooks/useQueue'; +import { useSearch } from '../hooks/useSearch'; +import { useFavorites } from '../hooks/useFavorites'; + +// ❌ Don't import from a general hooks index +// ❌ import { useQueue } from '../hooks'; +// βœ… Import from specific hook files +// βœ… import { useQueue } from '../hooks/useQueue'; +``` + +#### **5. Component Imports:** +```typescript +// Import components from their specific folders +import { SongItem } from '../components/common/SongItem'; +import { ActionButton } from '../components/common/ActionButton'; +import { Layout } from '../components/Layout/Layout'; + +// ❌ Don't import from general component indices +// ❌ import { SongItem } from '../components'; +// βœ… Import from specific component files +// βœ… import { SongItem } from '../components/common/SongItem'; +``` + +### **Architecture Flow:** +``` +UI Components β†’ Custom Hooks β†’ Redux State β†’ Firebase Services β†’ Firebase Database +``` + +### **Separation of Concerns:** +- **Components:** Only handle UI presentation and user interactions +- **Hooks:** Contain business logic and data management +- **Redux:** Manage global application state +- **Services:** Handle Firebase operations and data persistence +- **Types:** Define data structures and interfaces + +## Component Architecture + +### **React Component Structure:** + +#### **Page Components:** +```typescript +// src/features/Queue/Queue.tsx +interface QueueProps { + // Props interface +} + +const Queue: React.FC = () => { + // Component implementation +} +``` + +#### **Common Components:** +```typescript +// src/components/common/SongItem.tsx +interface SongItemProps { + song: Song; + onAddToQueue: (song: Song) => void; + onAddToFavorites: (song: Song) => void; + showAddButton?: boolean; + showFavoriteButton?: boolean; +} +``` + +#### **Layout Components:** +```typescript +// src/components/Layout/Layout.tsx +interface LayoutProps { + children: React.ReactNode; + title?: string; + showBackButton?: boolean; +} +``` + +### **Ionic Integration:** +- **IonPage** wrapper for all page components +- **IonHeader** with dynamic titles and action buttons +- **IonContent** with proper scrolling behavior +- **IonFooter** for player controls and queue management +- **IonLoading** for async operations and data fetching + +--- + +## State Management + +### **Redux Architecture Pattern:** +The web implementation uses Redux Toolkit for predictable state management with excellent TypeScript support. + +#### **Store Structure:** +```typescript +// src/redux/store.ts +export const store = configureStore({ + reducer: { + auth: authSlice, + player: playerSlice, + queue: queueSlice, + controller: controllerSlice, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: ['persist/PERSIST'], + }, + }), +}); +``` + +#### **Slice Patterns:** +```typescript +// src/redux/controllerSlice.ts +const controllerSlice = createSlice({ + name: 'controller', + initialState, + reducers: { + setController: (state, action) => { + state.data = action.payload; + }, + updateQueue: (state, action) => { + state.data.player.queue = action.payload; + }, + }, +}); +``` + +#### **Selectors:** +```typescript +// src/redux/selectors.ts +export const selectQueue = (state: RootState) => state.controller.data?.player?.queue || {}; +export const selectQueueLength = createSelector( + [selectQueue], + (queue) => Object.keys(queue).length +); +``` + +### **Redux Toolkit Implementation:** + +#### **Store Structure:** +```typescript +// src/redux/store.ts +export const store = configureStore({ + reducer: { + auth: authSlice, + player: playerSlice, + queue: queueSlice, + controller: controllerSlice, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: ['persist/PERSIST'], + }, + }), +}); +``` + +#### **Slice Patterns:** +```typescript +// src/redux/queueSlice.ts +const queueSlice = createSlice({ + name: 'queue', + initialState, + reducers: { + addToQueue: (state, action) => { + // Implementation + }, + removeFromQueue: (state, action) => { + // Implementation + }, + }, +}); +``` + +#### **Selectors:** +```typescript +// src/redux/selectors.ts +export const selectQueue = (state: RootState) => state.queue.items; +export const selectQueueLength = createSelector( + [selectQueue], + (queue) => queue.length +); +``` + +--- + +## Development Setup + +### **Project Configuration:** + +#### **Package.json Dependencies:** +```json +{ + "dependencies": { + "@ionic/react": "^7.0.0", + "@reduxjs/toolkit": "^1.9.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-redux": "^8.0.0", + "firebase": "^9.0.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "typescript": "^4.9.0", + "vite": "^4.0.0" + } +} +``` + +#### **Vite Configuration:** +```typescript +// vite.config.ts +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + build: { + outDir: 'dist', + sourcemap: true, + }, +}); +``` + +#### **TypeScript Configuration:** +```json +// tsconfig.json +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + } +} +``` + +### **Environment Setup:** +```bash +# .env.local +VITE_FIREBASE_API_KEY=your_api_key +VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com +VITE_FIREBASE_PROJECT_ID=your_project_id +VITE_FIREBASE_STORAGE_BUCKET=your_project.appspot.com +VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id +VITE_FIREBASE_APP_ID=your_app_id +VITE_FIREBASE_DATABASE_URL=https://your_project-default-rtdb.firebaseio.com +``` + +--- + +## Design Assets + +### **Web-Specific Mockups:** +Located in `design/` with 30+ mockups covering all features: + +#### **Core Navigation & Layout:** +- `00-web-layout.JPG` - Overall web layout structure +- `01-Login.png` - Login screen design +- `02-menu.jpeg`, `02a-menu.jpeg`, `02b-menu.png`, `02c-menu.jpeg` - Navigation menu variations + +#### **Queue Management:** +- `02-queue.png` - Main queue view +- `02-queue-delete.png` - Queue with delete functionality +- `02-queue-drag.png` - Queue reordering with drag and drop +- `02-queue-sorting.png` - Queue sorting interface + +#### **Search & Discovery:** +- `04-search.png` - Main search interface +- `04-search typing .png` - Search with typing interaction +- `04-search-song info.png` - Search results with song information + +#### **User Management:** +- `05-singers.png` - Singer list view +- `05-singers add.png` - Singer management interface + +#### **Content Browsing:** +- `06-artists .png` - Artist browse interface +- `06-artists (not admin).png` - Non-admin artist view +- `06-artists search.png` - Artist search functionality +- `06-artists songs.png` - Artist songs list + +#### **User Features:** +- `07-favorites.png` - Favorites management +- `08-history.png` - Play history view +- `09-songs list.png` - Main song lists view +- `09-song lists - songs.png` - Song lists with song details +- `09- song lists songs expand.png` - Song lists with expandable sections + +#### **Admin Features:** +- `10-Settings.png` - Settings interface +- `11-top 100.png` - Top played songs +- `12-favorites .png` - Favorites view +- `12-favorite lists.png` - Favorite lists management + +#### **Menu States:** +- `03-menu.png` - General menu layout +- `03-menu current page and non-admin.png` - Navigation with current page indicators +- `03-menu playing (admin).png` - Admin view during playback + +### **Design System:** +- **Ionic Design System** for consistent UI components +- **Custom CSS variables** for theming and branding +- **Responsive grid system** for layout consistency +- **Touch-friendly spacing** and sizing guidelines + +--- + +## Toolset Choices + +### **Current Web Implementation Toolset:** + +#### **Core Framework: React 18 + TypeScript** +- **Why:** Chosen for its component-based architecture, strong ecosystem, and excellent TypeScript support +- **Migration Note:** Can be replaced with any other component-based framework (e.g., Vue, Svelte) + +#### **State Management: Redux Toolkit** +- **Why:** Provides predictable state management with excellent TypeScript support and dev tools +- **Migration Note:** Can be replaced with Context API, Zustand, or other state management solutions + +#### **UI Framework: Ionic React** +- **Why:** Provides mobile-first UI components with excellent touch support and PWA capabilities +- **Migration Note:** Can be replaced with Material-UI, Chakra UI, or custom components + +#### **Build Tool: Vite** +- **Why:** Fast development server and optimized builds with excellent TypeScript support +- **Migration Note:** Can be replaced with Webpack, Parcel, or other build tools + +#### **Backend: Firebase Realtime Database** +- **Why:** Real-time synchronization, simple setup, and excellent React integration +- **Migration Note:** Can be replaced with any real-time database (Supabase, AWS AppSync, etc.) + +### **Development Tools:** +- **TypeScript:** Type safety and better developer experience +- **ESLint:** Code quality and consistency +- **Prettier:** Code formatting +- **React DevTools:** Component debugging +- **Redux DevTools:** State management debugging + +--- + +## Web-Specific Implementation Details + +### **Authentication & Session Management:** +- **Admin Access:** Triggered by URL parameter (`?admin=true`), removed after login +- **Session Persistence:** Lost on browser reload (no persistent storage) +- **Admin Mode:** Pre-fills singer name as "Admin" for convenience +- **URL Handling:** Admin parameter automatically removed from URL after authentication + +### **Search Implementation:** +- **Pagination:** Uses Ionic InfiniteScrollList component for efficient loading +- **Debouncing:** Search input debounced to prevent excessive API calls +- **Real-time Results:** Instant search results as user types +- **Context Actions:** Add to queue, favorite, and other actions available per song + +### **Queue Management:** +- **UI Controls:** Reordering and deletion exposed via UI controls only visible to admins +- **Drag & Drop:** Uses Ionic drag handles and swipe actions for reordering +- **Visual Feedback:** Clear indicators for admin-only actions +- **State Synchronization:** Real-time updates across all connected clients + +### **Favorites Implementation:** +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Real-time Sync:** Shared favorites list synchronized across all clients +- **Duplicate Prevention:** Prevents duplicates using song path field +- **User Actions:** Anyone can add/remove favorites + +### **New Songs Implementation:** +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Real-time Updates:** Shows recently added songs from newSongs node +- **Automatic Loading:** Progressive loading as user scrolls + +### **Artists Implementation:** +- **Modal Views:** Uses Ionic modals for artist song lists +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Search Integration:** Artist search functionality included +- **Song Counts:** Displays song count per artist + +### **Song Lists Implementation:** +- **Modal Interface:** Uses Ionic modals for viewing list contents +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Expandable Views:** Available versions shown with expandable sections +- **Availability Status:** Shows which songs are available in catalog + +### **History Implementation:** +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Automatic Tracking:** Songs automatically added when played +- **Timestamp Display:** Shows when each song was last played +- **Append-only:** History is append-only, shared across all clients + +### **Top Played Implementation:** +- **Infinite Scroll:** Uses Ionic InfiniteScrollList for pagination +- **Play Count Display:** Shows play count for each song +- **Real-time Updates:** Popular songs generated by backend +- **Backend Integration:** Based on history data + +### **Singer Management:** +- **Admin-only UI:** Singer management available only to admins via settings page +- **Unique Names:** Singer names must be unique and non-empty +- **Auto-addition:** Singers automatically added when they join +- **Last Join Tracking:** Tracks when each singer last joined + +### **Playback Control:** +- **Admin-only Controls:** Player controls only rendered for admins +- **State-based UI:** Play/pause/stop buttons shown/hidden based on current state +- **Queue Validation:** Play button disabled when queue is empty +- **Real-time Sync:** Playback state synchronized across all clients + +### **Error Handling & Sync:** +- **Toast Notifications:** Uses web-specific toast notifications for user feedback +- **Error Boundaries:** React error boundaries for component-level error handling +- **Retry Patterns:** Automatic retry for failed Firebase operations +- **Connection Monitoring:** Real-time connection status tracking + +### **Disabled Songs:** +- **Modal Management:** Disabled songs managed via modal dialog +- **Search & Filter:** Search and filter capabilities in management interface +- **Hash Storage:** Disabled songs stored using hash of song path +- **Admin-only Access:** Only admins can disable or enable songs + +### **Settings Implementation:** +- **Debug Logging:** Web-only feature, toggled via settings page +- **Admin-only Access:** Only admins can change player settings +- **Real-time Updates:** Settings changes synchronized across all clients +- **UI Controls:** Settings interface with toggle switches and controls + +### **Navigation Implementation:** +- **Admin-based Navigation:** Navigation adapts based on admin status +- **Hidden Pages:** Settings page only visible to admins +- **Role-based UI:** Different navigation options for different user roles +- **Dynamic Menus:** Menu items shown/hidden based on permissions + +### **UI/UX Implementation:** +- **Ionic React:** Uses Ionic React and Tailwind CSS for UI +- **Component Library:** Infinite scroll, swipe actions, modals, and toasts using Ionic components +- **Responsive Design:** Mobile-first approach with touch-friendly interface +- **Theme Support:** Light/dark mode support with consistent styling + +## Implementation Notes + +### **Critical Web-Specific Patterns:** + +#### **Firebase Integration:** +```typescript +// src/firebase/services.ts +export const queueService = { + addToQueue: async (song: Song, singerId: string) => { + const newKey = await getNextKey('queue'); + await set(ref(database, `queue/${newKey}`), { + songId: song.id, + singerId, + timestamp: Date.now(), + key: newKey, + }); + }, +}; +``` + +#### **Real-time Listeners:** +```typescript +// src/hooks/useQueue.ts +useEffect(() => { + const queueRef = ref(database, 'queue'); + const unsubscribe = onValue(queueRef, (snapshot) => { + const data = snapshot.val(); + if (data) { + const queueItems = Object.values(data) as QueueItem[]; + dispatch(setQueue(queueItems)); + } + }); + return () => unsubscribe(); +}, [dispatch]); +``` + +#### **Error Handling:** +```typescript +// src/hooks/useFirebaseSync.ts +const retryOperation = async (operation: () => Promise, maxRetries = 3) => { + for (let i = 0; i < maxRetries; i++) { + try { + await operation(); + return; + } catch (error) { + if (i === maxRetries - 1) throw error; + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); + } + } +}; +``` + +### **Hook Implementation Patterns:** + +#### **Custom Hook Structure:** +```typescript +// src/hooks/useQueue.ts +export const useQueue = () => { + const dispatch = useAppDispatch(); + const queue = useAppSelector(selectQueue); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const addToQueue = useCallback(async (song: Song, singerId: string) => { + try { + setLoading(true); + setError(null); + await queueService.addToQueue(song, singerId); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to add to queue'); + } finally { + setLoading(false); + } + }, []); + + return { + queue, + loading, + error, + addToQueue, + }; +}; +``` + +#### **Hook Dependencies:** +- **Hooks depend on Redux state** and services +- **Business logic** implemented in hooks, not components +- **Error handling** and loading states managed in hooks +- **Memoization** used for expensive operations + +#### **Hook Usage in Components:** +```typescript +// src/features/Queue/Queue.tsx +const Queue: React.FC = () => { + const { queue, loading, error, addToQueue } = useQueue(); + const { songs } = useSongs(); + + const handleAddToQueue = useCallback((song: Song) => { + addToQueue(song, currentSingerId); + }, [addToQueue, currentSingerId]); + + if (loading) return ; + if (error) return ; + + return ( + + {Object.values(queue).map((item) => ( + + ))} + + ); +}; +``` + +### **Performance Optimizations:** +- **React.memo** for expensive components +- **useMemo** and **useCallback** for expensive calculations +- **Redux selectors** with memoization +- **Lazy loading** for route-based code splitting +- **Service worker** for PWA caching + +### **Critical Implementation Rules:** +- **Never import directly from slice files** - always use the main redux index +- **Always use type imports** for TypeScript interfaces +- **Implement business logic in hooks**, not components +- **Use memoization** for expensive operations +- **Handle loading and error states** in all async operations + +--- + +## Migration Guide + +### **To Other Web Frameworks:** + +#### **Vue.js Migration:** +- Replace React components with Vue components +- Replace Redux with Pinia or Vuex +- Replace Ionic React with Ionic Vue +- Keep all business logic and Firebase integration + +#### **Svelte Migration:** +- Replace React components with Svelte components +- Replace Redux with Svelte stores +- Replace Ionic React with Ionic Svelte +- Keep all business logic and Firebase integration + +### **To Mobile Platforms:** + +#### **React Native Migration:** +- Replace Ionic components with React Native components +- Replace web-specific APIs with React Native APIs +- Keep Redux state management +- Keep all business logic and Firebase integration + +#### **Native iOS/Android Migration:** +- Replace React components with native UI components +- Replace Redux with native state management +- Keep all business logic and Firebase integration +- Adapt UI patterns to platform conventions + +--- + +_This document contains web-specific implementation details. For core business logic and platform-agnostic requirements, see the main `../../PRD.md`._ \ No newline at end of file diff --git a/docs/platforms/web/README.md b/docs/platforms/web/README.md new file mode 100644 index 0000000..dcf005d --- /dev/null +++ b/docs/platforms/web/README.md @@ -0,0 +1,132 @@ +# Web Platform Documentation + +> **Platform:** Web (React + Ionic + TypeScript) +> **Core Business Logic:** See `../../PRD.md` + +This folder contains **web-specific implementation details** for the Karaoke App. + +--- + +## πŸ“ File Structure + +``` +docs/platforms/web/ +β”œβ”€β”€ PRD-web.md # Web-specific implementation guide +└── README.md # This file - quick reference +``` + +--- + +## πŸš€ Quick Start + +### **For AI-Assisted Development:** +1. **Read the main PRD:** `../../PRD.md` (core business logic) +2. **Read this web PRD:** `PRD-web.md` (web implementation details) +3. **Follow the implementation guide** in the main PRD +4. **Reference design assets:** `design/` + +### **For Human Developers:** +1. **Review business requirements** in main PRD +2. **Study web implementation** patterns in `PRD-web.md` +3. **Set up development environment** using provided configs +4. **Follow component architecture** and state management patterns + +--- + +## πŸ“‹ What's Included + +### **PRD-web.md Contains:** +- **UI/UX Behavior** - Web-specific patterns and interactions +- **Component Architecture** - React/Ionic component structure +- **State Management** - Redux Toolkit implementation +- **Development Setup** - Project configuration and environment +- **Design Assets** - Web-specific visual references +- **Toolset Choices** - Technology rationale and migration notes +- **Implementation Notes** - Critical web-specific patterns +- **Migration Guide** - How to adapt to other platforms + +### **Key Web Technologies:** +- **React 18** + **TypeScript** for component architecture +- **Ionic React** for mobile-first UI components +- **Redux Toolkit** for state management +- **Firebase Realtime Database** for backend +- **Vite** for build tooling + +--- + +## πŸ”— Cross-References + +### **Main PRD Sections:** +- **Business Logic:** See `../../PRD.md#business-logic` +- **Data Models:** See `../../PRD.md#data-models` +- **User Roles:** See `../../PRD.md#user-roles` +- **Feature Specs:** See `../../PRD.md#feature-overview` + +### **Design Assets:** +- **Web Mockups:** See `design/` +- **30+ Visual References** for all features + +### **Implementation Guide:** +- **Core Requirements:** See `../../PRD.md#implementation-guide` +- **Web-Specific Details:** See `PRD-web.md#implementation-notes` + +--- + +## πŸ› οΈ Development Workflow + +### **1. Setup Project:** +```bash +# Install dependencies +npm install + +# Set up environment +cp .env.template .env.local +# Edit .env.local with your Firebase config + +# Start development server +npm run dev +``` + +### **2. Follow Architecture:** +- **Components:** Use React functional components with TypeScript +- **State:** Use Redux Toolkit for global state +- **Styling:** Use Ionic components with custom CSS variables +- **Data:** Use Firebase Realtime Database with custom hooks + +### **3. Reference Patterns:** +- **Firebase Integration:** See `PRD-web.md#firebase-integration` +- **Real-time Listeners:** See `PRD-web.md#real-time-listeners` +- **Error Handling:** See `PRD-web.md#error-handling` + +--- + +## πŸ”„ Migration Paths + +### **To Other Web Frameworks:** +- **Vue.js:** Replace React with Vue, Redux with Pinia +- **Svelte:** Replace React with Svelte, Redux with Svelte stores +- **Keep:** All business logic and Firebase integration + +### **To Mobile Platforms:** +- **React Native:** Replace Ionic with React Native components +- **Native iOS/Android:** Replace React with native UI frameworks +- **Keep:** All business logic and Firebase integration + +--- + +## πŸ“š Additional Resources + +### **Documentation:** +- **Main PRD:** `../../PRD.md` - Core business logic +- **Design Assets:** `design/` - Visual references +- **Type Definitions:** `../../types.ts` - Data models + +### **External Resources:** +- **Ionic React:** https://ionicframework.com/docs/react +- **Redux Toolkit:** https://redux-toolkit.js.org/ +- **Firebase:** https://firebase.google.com/docs +- **React:** https://react.dev/ + +--- + +_This document provides web-specific implementation details. For core business logic and platform-agnostic requirements, see the main `../../PRD.md`._ \ No newline at end of file diff --git a/docs/design/web/00-web-layout.JPG b/docs/platforms/web/design/00-web-layout.JPG similarity index 100% rename from docs/design/web/00-web-layout.JPG rename to docs/platforms/web/design/00-web-layout.JPG diff --git a/docs/design/web/01-Login.png b/docs/platforms/web/design/01-Login.png similarity index 100% rename from docs/design/web/01-Login.png rename to docs/platforms/web/design/01-Login.png diff --git a/docs/design/web/02-menu.jpeg b/docs/platforms/web/design/02-menu.jpeg similarity index 100% rename from docs/design/web/02-menu.jpeg rename to docs/platforms/web/design/02-menu.jpeg diff --git a/docs/design/web/02-queue-delete.png b/docs/platforms/web/design/02-queue-delete.png similarity index 100% rename from docs/design/web/02-queue-delete.png rename to docs/platforms/web/design/02-queue-delete.png diff --git a/docs/design/web/02-queue-drag.png b/docs/platforms/web/design/02-queue-drag.png similarity index 100% rename from docs/design/web/02-queue-drag.png rename to docs/platforms/web/design/02-queue-drag.png diff --git a/docs/design/web/02-queue-sorting.png b/docs/platforms/web/design/02-queue-sorting.png similarity index 100% rename from docs/design/web/02-queue-sorting.png rename to docs/platforms/web/design/02-queue-sorting.png diff --git a/docs/design/web/02-queue.png b/docs/platforms/web/design/02-queue.png similarity index 100% rename from docs/design/web/02-queue.png rename to docs/platforms/web/design/02-queue.png diff --git a/docs/design/web/02a-menu.jpeg b/docs/platforms/web/design/02a-menu.jpeg similarity index 100% rename from docs/design/web/02a-menu.jpeg rename to docs/platforms/web/design/02a-menu.jpeg diff --git a/docs/design/web/02b-menu.png b/docs/platforms/web/design/02b-menu.png similarity index 100% rename from docs/design/web/02b-menu.png rename to docs/platforms/web/design/02b-menu.png diff --git a/docs/design/web/02c-menu.jpeg b/docs/platforms/web/design/02c-menu.jpeg similarity index 100% rename from docs/design/web/02c-menu.jpeg rename to docs/platforms/web/design/02c-menu.jpeg diff --git a/docs/design/web/03-menu current page and non-admin.png b/docs/platforms/web/design/03-menu current page and non-admin.png similarity index 100% rename from docs/design/web/03-menu current page and non-admin.png rename to docs/platforms/web/design/03-menu current page and non-admin.png diff --git a/docs/design/web/03-menu playing (admin).png b/docs/platforms/web/design/03-menu playing (admin).png similarity index 100% rename from docs/design/web/03-menu playing (admin).png rename to docs/platforms/web/design/03-menu playing (admin).png diff --git a/docs/design/web/03-menu.png b/docs/platforms/web/design/03-menu.png similarity index 100% rename from docs/design/web/03-menu.png rename to docs/platforms/web/design/03-menu.png diff --git a/docs/design/web/04-search typing .png b/docs/platforms/web/design/04-search typing .png similarity index 100% rename from docs/design/web/04-search typing .png rename to docs/platforms/web/design/04-search typing .png diff --git a/docs/design/web/04-search-song info.png b/docs/platforms/web/design/04-search-song info.png similarity index 100% rename from docs/design/web/04-search-song info.png rename to docs/platforms/web/design/04-search-song info.png diff --git a/docs/design/web/04-search.png b/docs/platforms/web/design/04-search.png similarity index 100% rename from docs/design/web/04-search.png rename to docs/platforms/web/design/04-search.png diff --git a/docs/design/web/05-singers add.png b/docs/platforms/web/design/05-singers add.png similarity index 100% rename from docs/design/web/05-singers add.png rename to docs/platforms/web/design/05-singers add.png diff --git a/docs/design/web/05-singers.png b/docs/platforms/web/design/05-singers.png similarity index 100% rename from docs/design/web/05-singers.png rename to docs/platforms/web/design/05-singers.png diff --git a/docs/design/web/06-artists (not admin).png b/docs/platforms/web/design/06-artists (not admin).png similarity index 100% rename from docs/design/web/06-artists (not admin).png rename to docs/platforms/web/design/06-artists (not admin).png diff --git a/docs/design/web/06-artists .png b/docs/platforms/web/design/06-artists .png similarity index 100% rename from docs/design/web/06-artists .png rename to docs/platforms/web/design/06-artists .png diff --git a/docs/design/web/06-artists search.png b/docs/platforms/web/design/06-artists search.png similarity index 100% rename from docs/design/web/06-artists search.png rename to docs/platforms/web/design/06-artists search.png diff --git a/docs/design/web/06-artists songs.png b/docs/platforms/web/design/06-artists songs.png similarity index 100% rename from docs/design/web/06-artists songs.png rename to docs/platforms/web/design/06-artists songs.png diff --git a/docs/design/web/07-favorites.png b/docs/platforms/web/design/07-favorites.png similarity index 100% rename from docs/design/web/07-favorites.png rename to docs/platforms/web/design/07-favorites.png diff --git a/docs/design/web/08-history.png b/docs/platforms/web/design/08-history.png similarity index 100% rename from docs/design/web/08-history.png rename to docs/platforms/web/design/08-history.png diff --git a/docs/design/web/09- song lists songs expand.png b/docs/platforms/web/design/09- song lists songs expand.png similarity index 100% rename from docs/design/web/09- song lists songs expand.png rename to docs/platforms/web/design/09- song lists songs expand.png diff --git a/docs/design/web/09-song lists - songs.png b/docs/platforms/web/design/09-song lists - songs.png similarity index 100% rename from docs/design/web/09-song lists - songs.png rename to docs/platforms/web/design/09-song lists - songs.png diff --git a/docs/design/web/09-songs list.png b/docs/platforms/web/design/09-songs list.png similarity index 100% rename from docs/design/web/09-songs list.png rename to docs/platforms/web/design/09-songs list.png diff --git a/docs/design/web/10-Settings.png b/docs/platforms/web/design/10-Settings.png similarity index 100% rename from docs/design/web/10-Settings.png rename to docs/platforms/web/design/10-Settings.png diff --git a/docs/design/web/11-top 100.png b/docs/platforms/web/design/11-top 100.png similarity index 100% rename from docs/design/web/11-top 100.png rename to docs/platforms/web/design/11-top 100.png diff --git a/docs/design/web/12-favorite lists.png b/docs/platforms/web/design/12-favorite lists.png similarity index 100% rename from docs/design/web/12-favorite lists.png rename to docs/platforms/web/design/12-favorite lists.png diff --git a/docs/design/web/12-favorites .png b/docs/platforms/web/design/12-favorites .png similarity index 100% rename from docs/design/web/12-favorites .png rename to docs/platforms/web/design/12-favorites .png