initial commit

Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
Matt Bruce 2025-07-17 08:46:17 -05:00
commit 9c163c8e8f
4 changed files with 3026 additions and 0 deletions

176
docs/PRD.md Normal file
View File

@ -0,0 +1,176 @@
# 🎤 Karaoke Web App — Product Requirements Document (PRD)
---
## 1⃣ Purpose
This document defines the functional, technical, and UX requirements for the Karaoke Web 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).
- ✅ Ensure graceful handling of Firebase sync issues using retry patterns and partial node updates.
---
## 3⃣ User Roles & Permissions
| Role | Search Songs | Add Songs | Delete Songs | Reorder Queue | Playback Control | Manage Singers |
|--------------|---------------|-----------|--------------|----------------|------------------|----------------|
| **Host/Admin** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Singer/User** | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
---
## 4⃣ Feature Overview
- **Search:**
- Local, Redux-managed search on a preloaded song list.
- Common song item view with context-based action panel.
- **Queue Management:**
- Shared real-time synced queue.
- Admin can reorder; all users can delete songs.
- Duplicate prevention based on `fileLocation` field of each song.
- **Favorites:**
- Shared real-time synced.
- Anyone can do this
- Duplicate prevention based on `fileLocation` field of each song.
- **Latest Songs:**
- This is the newSongs node in the controller.
- Shared real-time synced.
- **Playback Control:**
- Managed by Admin only.
- Playback state synced to all clients using the `player` node in Firebase.
- The Player.state is mapped to the PlayerState enum in the types.ts.
- **History Tracking:**
- Songs added to history automatically when played.
- Append-only log, shared across clients.
- **Top Played:**
- Generated by a Firebase Cloud Function based on history.
- Stored inside the `controller` node for client reference.
- **Singer Management:**
- Admin can add/remove singers.
- All users can view the current singers list.
- **Error Handling:**
- Retry options for sync failures.
- Full controller object loaded on start; incremental sync after.
---
## 5⃣ Data Models
Data models are defined externally in:
> [`types.ts`](./types.ts)
This file contains TypeScript interfaces describing:
- `Song` — Used in queue, search results, and UI actions.
- `Controller` — Main object containing queue, singers, history, player state, and top played list.
- `PlayerState` — Playback status object synced in Firebase.
---
## 6⃣ Firebase Realtime Database Structure
Defined externally in:
> [`firebase_schema.json`](./firebase_schema.json)
Example structure:
```json
controllers: {
[controllerName]: {
favorites: { ... },
history: { ... },
topPlayed: { ... },
newSongs: { ... },
player: {
queue: { ... },
settings: { ... },
singers: { ... },
state: "..."
},
songList: { ... },
songs: { ... }
}
}
```
- Initial sync loads the full `controller` object.
- Subsequent updates target specific child nodes.
---
## 7⃣ UI/UX Behavior
- Shared **Empty State View** for empty lists or missing data.
- Toast notifications for user actions like add/remove/favorite.
- Playback controls only visible to Admin.
- Common song list item with dynamic action panel based on context (search, queue, history).
---
## 8⃣ Codebase Organization
| Folder | Purpose |
|--------|---------|
| `/components/common` | Shared UI components (EmptyState, Toast, ActionButton) |
| `/features` | Feature-specific components (Search, Queue, History, TopPlayed) |
| `/redux` | State management slices (controller, queue, player) |
| `/firebase` | Firebase CRUD and real-time sync services |
---
## 9⃣ Cloud Function Design — Top Played
- Triggered when a new song is added to `history`.
- Increments the play count inside `/controllers/{controllerName}/topPlayed/{songId}`.
- Ensures Top Played is up-to-date without blocking client-side actions.
---
## 🔟 External Reference Files
| File | Purpose |
|------|---------|
| [`types.ts`](./types.ts) | TypeScript interfaces for app data models and validation |
| [`firebase_schema.json`](./firebase_schema.json) | Firebase Realtime Database structure reference |
---
## 11⃣ 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 the queue.
- ✅ Singer is auto-added on join if not already present in the list.
- ✅ Data validated against `types.ts` before being written to Firebase.
**Assumed Environment:**
- The app is used in trusted, in-home scenarios with controlled participants.
- Open Firebase access is considered acceptable for this use case.
---
## ✅ Summary
This PRD serves as the primary 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.

37
docs/README.md Normal file
View File

@ -0,0 +1,37 @@
# 📄 Documentation & Reference Models
This `/docs` folder contains **Product Requirements Documents (PRD)**, **data model definitions**, and **Firebase schema references** for the Karaoke Web App project.
These files are intended for:
- 📃 Developers reviewing the business logic and architecture.
- 🤖 AI tools like Cursor or Copilot that reference documentation for context-aware coding.
- 📝 Project planning, architecture decisions, and future enhancements.
---
## Contents
| File | Purpose |
|------|---------|
| `PRD.md` | Primary Product Requirements Document — outlines business goals, functional specs, UI/UX notes, and data access model. |
| `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. |
---
## Important Notes
- ✅ These files are **not intended for direct import or use in application runtime**.
- ✅ Validation logic and data models here serve as **development references only**.
- ✅ Any updates to business logic, data flow, or app architecture should be reflected here for documentation purposes.
- ✅ AI tools may use this information to assist with code generation but will not access `/src` directly.
---
## How to Use
- Developers can reference these files during implementation, especially when defining CRUD operations or integrating Firebase sync.
- When using AI-assisted development tools, ensure they have access to the `/docs` folder for accurate context.
---
_If in doubt, assume these files are **guides, not code.**_

2737
docs/firebase_schema.json Normal file

File diff suppressed because it is too large Load Diff

76
docs/types.ts Normal file
View File

@ -0,0 +1,76 @@
export enum PlayerState {
playing = "Playing",
paused = "Paused",
stopped = "Stopped"
}
export interface Keyable {
key?: string;
}
export interface Authentication {
authenticated: boolean;
singer: string;
isAdmin: boolean;
controller: string;
}
export interface History {
songs: Song[],
topPlayed: TopPlayed[]
}
export interface Player {
state: PlayerState;
}
export interface QueueItem extends Keyable {
order: number,
singer: Singer;
song: Song;
}
export interface Settings {
autoadvance: boolean;
userpick: boolean;
}
export interface Singer extends Keyable {
name: string;
lastLogin: string;
}
export interface SongBase extends Keyable {
path: string;
}
export interface Song extends SongBase {
artist: string;
title: string;
count?: number;
disabled?: boolean;
favorite?: boolean;
date?: string;
}
export type PickedSong = {
song: Song
}
export interface SongList extends Keyable {
title: string;
songs: SongListSong[];
}
export interface SongListSong extends Keyable {
artist: string;
position: number;
title: string;
foundSongs?: Song[];
}
export interface TopPlayed extends Keyable {
artist: string;
title: string;
count: number;
}