commits
playback-router: go watch streams on other servers
Add stage switching for AtMoCo
fix: add webp encoder to og image
federated viewership
fix: add styling to HLS to have it not be 0x0px on mobile
feat: compacter mobile portrait mode
fix: add 'collapse sidebar' buttons to every stack possible
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add !no-viewers label and IsViewerBanned() check. When indexing a
LiveViewCount record from the firehose, check if the reporting
server's DID has any banned labels or !no-viewers — if so, discard
the record. The 2-minute go-cache TTL naturally handles cleanup
when a label is applied after records were already cached.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a LiveViewCount record arrives via firehose, store it in a
go-cache (2min TTL) keyed by streamer:server. GetViewerCount now
sums local HLS connections + all federated counts, so the websocket,
HTTP API, and getLiveUsers XRPC all automatically include federated
viewer counts with no additional changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the websocket just replayed historical events and hung open.
Now the server PDS subscribes to a notification channel and pushes new
commit events to connected clients as they happen. Uses a simple
pub/sub: CommitServerRepoRecord -> CreateServerCommitEvent -> notify
all subscriber channels -> websocket handler writes to client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PutRecord/UpdateRecord return the record CID — capture it and set
it on the RepoOp so relay consumers see the correct CID. Also
correctly distinguish create vs update action.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a viewCountUpdateLoop to StreamSession that writes LiveViewCount
records to the server repo every 30s during active streams. Uses the
same throttled background worker pattern as the other update loops.
Record key format: {streamer_did}::{server_did} matching BroadcastOrigin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server PDS (ServerHost) serves the server repo, broadcaster PDS
(BroadcasterHost) serves the lexicon repo. Single-node case
(ServerHost == BroadcasterHost) always uses the server PDS — the
lexicon repo is not directly exposed. Server repo is now always
created regardless of host configuration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each server node gets its own atproto repository (did:web:{ServerHost})
with a file-backed SQLite carstore and local commit event DB for relay
replay. Only created when ServerHost differs from BroadcasterHost.
XRPC sync and repo endpoints now serve both the lexicon repo and server
repo, routing by DID. DID document serving is host-aware.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add UI pin controls (preset durations), a pinned comment notification
banner, websocket/server support to broadcast the active pin, and DB/
lexicon/schema changes to record the pinner and TTL
Co-authored-by: Eli Mallon <eli@stream.place>
fix: lazyize/memoize navigation and such
feat: add params to chat popout, align better without hax
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add !no-viewers label and IsViewerBanned() check. When indexing a
LiveViewCount record from the firehose, check if the reporting
server's DID has any banned labels or !no-viewers — if so, discard
the record. The 2-minute go-cache TTL naturally handles cleanup
when a label is applied after records were already cached.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a LiveViewCount record arrives via firehose, store it in a
go-cache (2min TTL) keyed by streamer:server. GetViewerCount now
sums local HLS connections + all federated counts, so the websocket,
HTTP API, and getLiveUsers XRPC all automatically include federated
viewer counts with no additional changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the websocket just replayed historical events and hung open.
Now the server PDS subscribes to a notification channel and pushes new
commit events to connected clients as they happen. Uses a simple
pub/sub: CommitServerRepoRecord -> CreateServerCommitEvent -> notify
all subscriber channels -> websocket handler writes to client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a viewCountUpdateLoop to StreamSession that writes LiveViewCount
records to the server repo every 30s during active streams. Uses the
same throttled background worker pattern as the other update loops.
Record key format: {streamer_did}::{server_did} matching BroadcastOrigin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server PDS (ServerHost) serves the server repo, broadcaster PDS
(BroadcasterHost) serves the lexicon repo. Single-node case
(ServerHost == BroadcasterHost) always uses the server PDS — the
lexicon repo is not directly exposed. Server repo is now always
created regardless of host configuration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each server node gets its own atproto repository (did:web:{ServerHost})
with a file-backed SQLite carstore and local commit event DB for relay
replay. Only created when ServerHost differs from BroadcasterHost.
XRPC sync and repo endpoints now serve both the lexicon repo and server
repo, routing by DID. DID document serving is host-aware.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>