initial commit
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
commit
9c163c8e8f
176
docs/PRD.md
Normal file
176
docs/PRD.md
Normal 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
37
docs/README.md
Normal 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
2737
docs/firebase_schema.json
Normal file
File diff suppressed because it is too large
Load Diff
76
docs/types.ts
Normal file
76
docs/types.ts
Normal 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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user