Overview

Speechwave lets a speaker’s audience react to a talk in real time, with emojis that show up right on the slides. Under the hood, that experience comes from three actors talking to a Phoenix server.

📱 Attendee Phone browser, /t/:slug
taps an emoji over /live
Phoenix server Rate-limits, persists, broadcasts
relays it over /socket
💻 Speaker Chrome extension, overlays slides

The attendee opens a talk’s URL on their phone and gets a plain web page powered by Phoenix LiveView. The server takes each tap, checks it against a rate limit, stores it if a session is recording, and broadcasts it to everyone listening. The speaker runs a Chrome extension on their laptop that listens for those broadcasts and draws the emoji on top of Google Slides.

Two separate WebSocket connections carry that traffic, and it’s worth knowing them apart early, because later chapters refer back to this table constantly.

ConnectionPathProtocolUsed by
LiveView socket /live Phoenix LiveView The attendee's browser
Channel socket /socket Phoenix Channel The Chrome extension

The full chapter on this is WebSockets, but the short version: a single server-side broadcast reaches both kinds of listener without either side knowing the other exists.

Project structure

Here’s the shape of the codebase, trimmed to the parts these chapters actually walk through.

Project structure
lib/speechwave/                     core domain logic, no web concerns
  application.ex                    supervision tree, see Supervision tree
  talks.ex                          talks and talk sessions
  reactions.ex                      emoji reactions and slide aggregation
  accounts.ex                       users, tokens, identities
  plans.ex                          plan tiers and limits
  rate_limiter.ex                   per-connection cooldown
  auth_throttle.ex                  magic-link send throttling
  db_backup.ex                      scheduled snapshot uploads

lib/speechwave_web/
  live/
    talk_live.ex                    the attendee's page
    dashboard_live.ex               the speaker's talk list
    session_analytics_live.ex       post-talk engagement review
  channels/
    user_socket.ex                  the /socket entry point
    reaction_channel.ex             join checks, session and slide messages
  endpoint.ex                       both socket mounts live here
  router.ex                         routes and live_session scopes

chrome-extension/                   separate repo, see Chrome extension

Each piece gets its own chapter. Start with talks.ex and reactions.ex in Data model if you want to see how the pieces are actually stored.


This site uses Just the Docs, a documentation theme for Jekyll.