Skip to content

Commit fa78a01

Browse files
Merge pull request #41 from Jamesllllllllll/codex/issue-39-unify-playlist-surface
Unify channel playlist management
2 parents 888fa17 + 6792d7b commit fa78a01

40 files changed

+5977
-3529
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ To test Twitch sign-in, bot behavior, and EventSub locally, also set:
106106

107107
`ADMIN_TWITCH_USER_IDS` should contain the Twitch user ID for the admin account that is allowed to connect the shared bot account and access admin pages.
108108

109-
If a broadcaster connected before `channel:bot`, `channel:read:subscriptions`, or `bits:read` were added to your configured scopes, they need to reconnect Twitch from the app before bot replies and VIP token automation can use the updated Twitch permissions.
109+
Broadcaster connections need `channel:bot`, `channel:read:subscriptions`, and `bits:read` in `TWITCH_SCOPES`. If the connected Twitch account is missing those permissions, reconnect Twitch from the app so bot replies and VIP token automation can use them.
110110

111111
Sentry stays off locally unless you explicitly set a DSN:
112112

biome.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"*.jsonc",
1010
"*.js",
1111
"*.ts",
12-
"*.tsx"
12+
"*.tsx",
13+
"!!**/src/routeTree.gen.ts"
1314
]
1415
},
1516
"formatter": {
@@ -30,6 +31,11 @@
3031
"trailingCommas": "es5"
3132
}
3233
},
34+
"css": {
35+
"parser": {
36+
"tailwindDirectives": true
37+
}
38+
},
3339
"overrides": [
3440
{
3541
"includes": [

docs/bot-operations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The app treats the Twitch bot as a separate shared account from the broadcaster:
88

99
- The streamer signs into the app with their own Twitch account.
1010
- An admin signs the shared bot account into the app once.
11-
- Each streamer can opt their own channel into bot presence from Dashboard Settings.
11+
- Each streamer can opt their own channel into bot presence from the owner Settings area.
1212
- When an opted-in streamer goes live, the app activates the bot in that channel by ensuring the `channel.chat.message` EventSub subscription exists for that broadcaster + bot user pair.
1313
- When the streamer goes offline, the app removes that chat subscription so the bot is inactive in the channel.
1414

@@ -45,7 +45,7 @@ TWITCH_SCOPES=openid user:read:moderated_channels moderator:read:chatters channe
4545

4646
For local development, `TWITCH_BOT_USERNAME` should usually be your dedicated test bot account. Production should keep its own bot username in deployed env or secrets. The app enforces that the connected bot login matches `TWITCH_BOT_USERNAME`, so changing bot accounts locally requires changing local `.env` first.
4747

48-
`TWITCH_SCOPES` belongs to the broadcaster login flow, not the bot login flow. It should include `channel:bot` so chat replies can use Twitch's bot badge path. If a broadcaster connected before `channel:bot` was present, they need to reconnect Twitch.
48+
`TWITCH_SCOPES` belongs to the broadcaster login flow, not the bot login flow. It should include `channel:bot` so chat replies can use Twitch's bot badge path. If the connected broadcaster account is missing that permission, reconnect Twitch.
4949

5050
2. Make sure your Twitch developer application has both redirect URIs registered:
5151

@@ -61,7 +61,7 @@ npm run db:migrate
6161
4. Start the app and log in with your broadcaster account.
6262
5. Go to `/dashboard/admin` as your admin user and click `Connect bot account`.
6363
6. Complete that OAuth flow while logged into the Twitch bot account named in `TWITCH_BOT_USERNAME`.
64-
7. Go to `/dashboard/settings` for your streamer account and enable `Enable bot for my channel`, then save.
64+
7. Go to `/dashboard/settings` for your streamer account and enable `Enable playlist on your channel`, then save.
6565
8. Go live on Twitch.
6666
9. Confirm the Settings page changes to `Active`.
6767
10. Send a chat request like:
Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
# Channel-First Architecture Refactor Plan
2+
3+
## Goal
4+
5+
Refactor the application from a dashboard-centric model to a channel-first model where:
6+
7+
- The public channel playlist page (`/$slug`) is the primary application surface.
8+
- The page behavior changes by role rather than by separate route families.
9+
- Owner-only configuration moves into a smaller settings/account area.
10+
- Moderator capabilities are explicitly configurable by the channel owner.
11+
- Polling can be replaced later by a clean real-time solution, but that is not a prerequisite for the structural refactor.
12+
13+
## Desired Product Model
14+
15+
### Primary surfaces
16+
17+
1. Home / discovery
18+
- Shows current streamers/channels.
19+
- Lets users find and open a channel playlist quickly.
20+
- Uses a channel-first content layout:
21+
- one featured live channel card
22+
- smaller secondary live channel cards
23+
- Prioritizes loading for the featured live preview image.
24+
- Leaves secondary preview images lazy-loaded.
25+
- If Twitch exposes only size variants rather than explicit quality variants, prefer:
26+
- featured image with eager/high-priority loading
27+
- smaller card images with smaller requested dimensions and lazy loading
28+
29+
2. Channel playlist page (`/$slug`)
30+
- Logged out:
31+
- View queue and played history.
32+
- Search songs and get request guidance.
33+
- See public blacklist / public channel info.
34+
- Logged-in viewer:
35+
- Everything logged-out users can do.
36+
- Viewer-specific request affordances.
37+
- Personal request context where applicable.
38+
- Logged-in moderator / owner:
39+
- Queue controls.
40+
- Moderation panels gated by owner-configured permissions.
41+
- Same unified song-add experience with role-aware actions.
42+
43+
3. Owner settings area
44+
- Channel configuration.
45+
- Bot settings.
46+
- Overlay settings.
47+
- Moderator permission settings.
48+
- Channel policy settings.
49+
50+
4. Optional personal account area
51+
- Twitch connection / reauthorization.
52+
- User-level preferences.
53+
- Managed channel list if needed.
54+
55+
### Core principle
56+
57+
There should not be one UI for "dashboard playlist management" and another for "public playlist viewing." There should be a single canonical playlist surface with capability-driven controls.
58+
59+
## Current Architecture Problems
60+
61+
- Dashboard and public channel routes still split responsibility.
62+
- Multiple route families expose overlapping channel-management concerns:
63+
- `src/routes/dashboard/*.tsx`
64+
- `src/routes/api/dashboard/*`
65+
- `src/routes/$slug/index.tsx`
66+
- `src/routes/api/channel/$slug/*`
67+
- Navigation still carries dashboard-era assumptions:
68+
- dashboard sidebar sections
69+
- `/dashboard/playlist` compatibility route
70+
- dashboard moderation and overlay pages
71+
- Access is mostly role-based, but not yet capability-based.
72+
- Moderator access is not granular enough for future product requirements.
73+
- Some management UI is still implemented as "dashboard components embedded into public route" rather than truly channel-first modules.
74+
75+
## Target Architecture
76+
77+
### Routing direction
78+
79+
#### Keep
80+
81+
- `src/routes/index.tsx`
82+
- `src/routes/search.tsx`
83+
- `src/routes/$slug/index.tsx`
84+
- `src/routes/$slug/stream-playlist/$token.tsx`
85+
- `src/routes/dashboard/settings.tsx` or equivalent owner settings route
86+
- `src/routes/dashboard/admin.tsx` if admin remains distinct
87+
88+
#### Shrink or remove
89+
90+
- `src/routes/dashboard/playlist.tsx`
91+
- `src/routes/dashboard/moderation.tsx`
92+
- `src/routes/dashboard/overlay.tsx`
93+
- `src/routes/dashboard/index.tsx`
94+
- `src/routes/dashboard/route.tsx`
95+
96+
#### Eventual shape
97+
98+
- Minimal dashboard shell or no dashboard shell.
99+
- If retained, dashboard should be settings/account-centric, not operations-centric.
100+
- Operations happen on `/$slug`.
101+
102+
### Data/API direction
103+
104+
#### Channel-first APIs should become canonical
105+
106+
- `src/routes/api/channel/$slug/playlist/route.ts`
107+
- `src/routes/api/channel/$slug/viewers.ts`
108+
- `src/routes/api/channel/$slug/played/*`
109+
110+
#### Dashboard APIs to shrink, merge, or retire
111+
112+
- `src/routes/api/dashboard/playlist/route.ts`
113+
- `src/routes/api/dashboard/moderation.ts`
114+
- `src/routes/api/dashboard/overlay.ts`
115+
- `src/routes/api/dashboard/settings.ts`
116+
117+
### UI/module direction
118+
119+
Extract capability-oriented channel modules rather than dashboard pages:
120+
121+
- `ChannelPlaylistView`
122+
- `ChannelQueueManagement`
123+
- `ChannelBlacklistManagement`
124+
- `ChannelBlockedChattersManagement`
125+
- `ChannelVipTokenPanel`
126+
- `ChannelOwnerSettings`
127+
- `ChannelModeratorCapabilitySettings`
128+
129+
These should be composable into `/$slug` and owner settings routes without importing "dashboard page" concepts.
130+
131+
## Permission Model Refactor
132+
133+
### Current model
134+
135+
- `anonymous`
136+
- `viewer`
137+
- `moderator`
138+
- `owner`
139+
140+
### Target model
141+
142+
Keep the role model, but add capability flags controlled by the owner.
143+
144+
Suggested capabilities:
145+
146+
- `can_manage_queue`
147+
- `can_manage_blacklist`
148+
- `can_manage_blocked_chatters`
149+
- `can_manage_vip_tokens`
150+
- `can_view_vip_tokens`
151+
- `can_manage_played_history`
152+
- `can_manage_request_priority`
153+
- `can_manage_session_reset`
154+
- `can_manage_overlay`
155+
156+
### Product rules
157+
158+
- Owner always has all capabilities.
159+
- Moderator gets only the capabilities the owner enables.
160+
- Viewer never gets moderator capabilities.
161+
- Read-only capability should be supported where management is too broad.
162+
- VIP tokens should explicitly support:
163+
- hidden
164+
- read-only
165+
- manage
166+
167+
## Proposed Delivery Phases
168+
169+
## Phase 0: Stabilize The Current Branch
170+
171+
- [x] Keep useful backend instrumentation while we refactor.
172+
- [x] Avoid coupling this phase to SSE reliability work.
173+
174+
## Phase 1: Define The New Navigation Model
175+
176+
- [x] Decide whether dashboard remains as a shell or becomes a small settings area.
177+
- [x] Reduce dashboard navigation to:
178+
- [x] settings
179+
- [x] admin (if applicable)
180+
- [x] optional account/manage channels page
181+
- [x] Remove dashboard nav items that point to operational channel views.
182+
- [x] Ensure all playlist-management entry points navigate directly to `/$slug`.
183+
- [x] Rework homepage live channel cards into:
184+
- [x] one featured live card
185+
- [x] smaller secondary cards
186+
- [x] prioritized featured image loading
187+
- [x] lazy-loaded secondary previews
188+
- [x] Move overlay configuration into owner settings instead of a separate primary dashboard destination.
189+
190+
## Phase 2: Formalize Capability Settings
191+
192+
- [x] Design the current channel settings schema for moderator capabilities.
193+
- [x] Add database fields or structured settings storage for current capability flags.
194+
- [x] Add validation/types for current capability flags.
195+
- [x] Expose owner-only API endpoints for updating current capability settings.
196+
- [x] Add server-side capability evaluation helpers.
197+
- [x] Expand the capability model beyond the current booleans.
198+
- [x] Add blocked-chatter and VIP-token visibility/manage capability splits.
199+
- [x] Add tests for capability enforcement across owner, moderator, viewer, and anonymous states.
200+
201+
## Phase 3: Break Dashboard Concepts Out Of The Public Route
202+
203+
- [x] Stop treating `PlaylistManagementSurface` as a dashboard page reused in public.
204+
- [x] Extract role-aware channel management components from dashboard files.
205+
- [x] Move shared logic into channel-focused modules under `src/components` or `src/features`.
206+
- [x] Make `/$slug` the canonical composition point for:
207+
- [x] public queue
208+
- [x] viewer actions
209+
- [x] moderator controls
210+
- [x] owner controls
211+
212+
## Phase 4: Collapse Dashboard Playlist And Moderation Pages
213+
214+
- [x] Remove operational use of `src/routes/dashboard/playlist.tsx`.
215+
- [x] Move moderation controls from `src/routes/dashboard/moderation.tsx` to `/$slug`.
216+
- [x] Move any overlay operational shortcuts that belong to channel management into owner settings or channel tools.
217+
- [x] Delete old operational dashboard routes once no navigation or API paths depend on them.
218+
219+
## Phase 5: Rework Owner Settings Area
220+
221+
- [x] Create a smaller owner-focused settings IA.
222+
- [x] Group settings by concern:
223+
- [x] bot / Twitch
224+
- [x] request policy
225+
- [x] overlay
226+
- [x] moderator permissions
227+
- [x] VIP token rules
228+
- [x] Ensure mods never see owner-only settings.
229+
230+
## Phase 6: Simplify APIs Around Channel Scope
231+
232+
- [x] Audit all `/api/dashboard/*` routes.
233+
- [x] Move channel-scoped operations under `/api/channel/$slug/*`.
234+
- [x] Reserve dashboard/account APIs for owner/account settings only.
235+
- [x] Remove dashboard aliases once callers are migrated.
236+
237+
## Phase 7: Real-Time Revisit
238+
239+
- [ ] After the structural refactor, revisit SSE as a separate effort.
240+
- [ ] Implement a minimal, validated SSE proof first.
241+
- [ ] Add immediate ready event and heartbeat.
242+
- [ ] Validate local dev, tunnel, and deployed dev before removing polling.
243+
244+
## Concrete File-Level Migration Checklist
245+
246+
### Navigation and route structure
247+
248+
- [x] Refactor `src/routes/dashboard/route.tsx`
249+
- [x] Refactor `src/routes/dashboard/index.tsx`
250+
- [x] Decide fate of `src/routes/dashboard/playlist.tsx`
251+
- [x] Decide fate of `src/routes/dashboard/moderation.tsx`
252+
- [x] Decide fate of `src/routes/dashboard/overlay.tsx`
253+
- [x] Refactor active-state logic in `src/routes/__root.tsx`
254+
255+
### Public channel page
256+
257+
- [~] Refactor `src/routes/$slug/index.tsx` into smaller channel-focused sections
258+
- [~] Separate view-only, viewer, moderator, and owner fragments
259+
- [x] Remove any remaining dashboard-specific assumptions from channel page composition
260+
261+
### APIs
262+
263+
- [~] Audit `src/routes/api/channel/$slug/playlist/route.ts`
264+
- [ ] Audit `src/routes/api/channel/$slug/viewers.ts`
265+
- [x] Add `src/routes/api/channel/$slug/moderation.ts`
266+
- [x] Add `src/routes/api/channel/$slug/moderation/search.ts`
267+
- [x] Audit `src/routes/api/dashboard/playlist/route.ts`
268+
- [x] Audit `src/routes/api/dashboard/moderation.ts`
269+
- [x] Audit `src/routes/api/dashboard/overlay.ts`
270+
- [x] Audit `src/routes/api/dashboard/settings.ts`
271+
272+
### Shared logic and permissions
273+
274+
- [x] Extend `src/lib/server/playlist-management.ts`
275+
- [x] Introduce capability evaluation helpers
276+
- [x] Add owner-configurable moderator capability settings
277+
- [x] Add tests for role + capability combinations
278+
279+
## Suggested Implementation Order
280+
281+
1. Navigation simplification
282+
2. Capability schema and server-side authorization
283+
3. Channel page component decomposition
284+
4. Migrate moderation tools into `/$slug`
285+
5. Reduce dashboard to settings/account
286+
6. Delete obsolete dashboard routes/APIs
287+
7. Revisit SSE
288+
289+
## Things We Can Probably Delete By The End
290+
291+
- Dashboard playlist page as an operational surface
292+
- Dashboard moderation page as an operational surface
293+
- Dashboard overlay page if overlay becomes owner settings only
294+
- Dashboard playlist bridge logic
295+
- Dashboard-specific playlist streaming path if channel-scoped real-time is sufficient
296+
297+
## Things We Should Not Delete Prematurely
298+
299+
- Polling until real-time is proven stable
300+
- Owner settings routes before the replacement IA exists
301+
- Any API aliases still actively used by existing views
302+
- Helpful backend logging until the refactor stabilizes
303+
304+
## Definition Of Done
305+
306+
- [x] `/$slug` is the canonical playlist and moderation surface.
307+
- [x] Logged-out, viewer, moderator, and owner experiences are all role/capability variants of the same route.
308+
- [x] Dashboard is settings/account oriented or removed entirely.
309+
- [x] Moderator abilities are owner-configurable and enforced server-side.
310+
- [x] Old dashboard operational pages are deleted.
311+
- [x] Polling remains acceptable until SSE is validated separately.
312+
313+
## Immediate Next Slice
314+
315+
Start with navigation and IA, not permissions storage.
316+
317+
- [x] Remove dashboard operational navigation items except settings/admin.
318+
- [x] Decide whether `/dashboard` becomes a settings landing page or a simple channel/account hub.
319+
- [x] Rename or replace dashboard language so users are guided toward channel pages, not dashboard tools.
320+
- [x] Identify which sections from dashboard moderation belong on `/$slug` first.
321+
- [x] Move blacklist and setlist management onto `/$slug`.
322+
- [x] Move blocked chatters and VIP token management onto `/$slug` or into owner settings.
323+
- [x] Improve homepage live channel presentation with featured + secondary card hierarchy.
324+
- [ ] Collapse or redirect remaining operational dashboard routes once their replacements are ready.

docs/local-development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ npm run dev
6161

6262
- public pages
6363
- search
64-
- dashboard UI
64+
- account/settings UI
6565
- playlist management flows
6666

6767
To exercise Twitch login, EventSub, and bot replies, fill in the Twitch-related values in `.env`.

0 commit comments

Comments
 (0)