# Streaming Page Plan ## Overview Add a streaming page (`stream.html`) for users who stream live content. The page implements [NIP-53 Live Activities](reference_repos/nips/53.md) using `kind:30311` (Live Streaming Event) and `kind:1311` (Live Chat Message). The streamer can manage their live event, view their stream, and interact with chat — all using existing components like [`mountComposer()`](www/js/post-composer.mjs:152) and [`post-interactions.mjs`](www/js/post-interactions.mjs:1). ## NIP-53 Summary ### kind:30311 — Live Streaming Event (addressable) An addressable event the streamer publishes and updates throughout the stream lifecycle: ``` tags: ["d", ""] ["title", ""] ["summary", ""] ["image", ""] ["streaming", ""] // HLS/m3u8 or other stream URL ["status", "planned|live|ended"] ["starts", ""] ["ends", ""] ["t", ""] ["current_participants", ""] ["total_participants", ""] ["p", "", "", ""] ["relays", "wss://...", ...] ["recording", ""] // post-stream recording ["pinned", ""] // pinned chat message ``` ### kind:1311 — Live Chat Message Chat messages scoped to a live event via an `a` tag: ``` tags: ["a", "30311::", "", "root"] content: "" ``` ## Architecture ```mermaid graph TD A[stream.html] --> B[init-ndk.mjs - auth + NDK] A --> C[post-composer.mjs - chat input] A --> D[post-interactions.mjs - render chat messages] A --> E[Video Player - HLS embed] subgraph Nostr Events F[kind:30311 - Live Event - publish/subscribe] G[kind:1311 - Chat Messages - publish/subscribe] end A --> F A --> G C -->|onSubmit publishes kind:1311| G D -->|renders incoming kind:1311| G ``` ## CSS Strategy — Reuse client.css The existing [`client.css`](www/css/client.css:1) and [`post-composer.css`](www/css/post-composer.css:1) provide nearly everything needed. Here is the mapping: ### Existing classes to reuse (NO new CSS needed) | Element | Existing class/ID | Source | |---------|-------------------|--------| | Body flex column layout | `#divBody` override pattern | [`client.css:356`](www/css/client.css:356) — override with `flex-direction: column !important` per rules | | Buttons | `.btn` | [`client.css:591`](www/css/client.css:591) | | Post cards for chat messages | `.divPostItem` | [`client.css:900`](www/css/client.css:900) | | Author header in chat | `.divPostHeader`, `.divPostHeaderMain`, `.divPostProfileLink` | [`client.css:1360`](www/css/client.css:1360) | | Avatar | `.divPostAvatar`, `.avatar--sm` | [`client.css:1424`](www/css/client.css:1424), [`client.css:1395`](www/css/client.css:1395) | | Author name | `.divPostAuthorName` | [`client.css:1438`](www/css/client.css:1438) | | Post content | `.divPostContent` | [`client.css:930`](www/css/client.css:930) | | Timestamp | `.divPostTime` | [`client.css:973`](www/css/client.css:973) | | Interaction bar | `.divPostInteractions`, `.interaction-item` | [`client.css:990`](www/css/client.css:990) | | Comment threads | `.divCommentThread`, `.divCommentsList` | [`client.css:1148`](www/css/client.css:1148) | | Hidden/visible | `.clsHidden`, `.clsVisible` | [`client.css:878`](www/css/client.css:878) | | Nostr embeds | `.nostr-embed`, `.nostr-mention`, etc. | [`client.css:215`](www/css/client.css:215) | | Composer wrapper | `.post-composer-wrapper`, `.post-composer-wrapper--inline` | [`post-composer.css:1`](www/css/post-composer.css:1) | | Video in posts | `.divPostContent video` | [`client.css:951`](www/css/client.css:951) | ### Minimal page-specific `