Live, signal-driven reading experience (SSE)

Live, signal-driven reading experience (SSE)

#12 in tonybierman/dx-blog — merged 2026-05-29

What

Adds the Live, signal-driven reading experience from TODO_ROADMAP.md — a real-time layer over the reader page, pushed via Server-Sent Events. All four sub-features, all anonymous (deduped by the existing visitor_hash fingerprint record_view uses).

  • "N reading now" presence — ephemeral, in-memory distinct-visitor count per post, broadcast on connect/disconnect.
  • Live comments — approved comments stream in without a refresh.
  • Optimistic comment posting — your comment appears instantly and reconciles on the server ack (pending → "awaiting approval").
  • Floating reactions/claps — a clap floats up in every reader's window in real time, with a server-authoritative running total.

How

  • src/server/live.rs (new) — in-memory LiveHub: one tokio::sync::broadcast channel per post plus a presence tally. A PresenceGuard decrements presence and GCs the channel on disconnect. GET /api/live/{post_id} is a raw axum SSE handler (like the XML feed routes), with a LiveStream wrapper tying the guard to the connection lifetime.
  • src/server/reactions.rs (new) — add_reaction (anonymous, anti-flood mirroring the comment throttle) + reaction_total; broadcasts the authoritative total with each clap.
  • create_comment now returns the created CommentView and broadcasts it when approved; moderate_comment broadcasts on the pending→approved transition.
  • The hub is layered as an axum::Extension before arium_dioxus::install, reaching both the SSE route and the server fns.
  • src/live.rs (new) — use_live hook + LiveHandle; consumes the browser EventSource via gloo-net (using futures-util, not the futures facade — the facade resolves Stream to a different path than gloo-net's subscription impl). Inert during SSR, mirroring the embeds' post-hydration pattern.
  • New reactions table (idempotent DDL); LiveEvent wire enum; clap-float CSS keyframes.

Verification

  • Both CI clippy targets clean (server,sqlite and web/wasm, -D warnings) + cargo fmt --check.
  • Manual two-window e2e confirmed: presence count, live comment streaming, optimistic post reconcile, and a clap floating in both windows with counts converging.

Note: multiple tabs of one browser on one machine share a visitor_hash, so they count as a single reader by design — a second browser shows 2.

🤖 Generated with Claude Code

Last updated 2026-05-30