Data model
Three tables carry the whole reaction flow: a talk, its sessions, and the reactions tapped during them. Account tables like users and user_identities live in Authentication instead, so they’re covered once rather than twice.
talks
One row per conference talk, owned by a user.
| Field | Type | Notes |
|---|---|---|
| title | string | What the speaker sees on their dashboard |
| slug | string | Unique, auto-generated from the title, URL-safe |
| user_id | references | Owning speaker |
The slug is the thread that ties all three actors together: it’s in the attendee’s URL, it’s the PubSub topic name, and it’s the Channel topic the extension joins. One string, three jobs.
talk_sessions
A recording window within a talk. A speaker can run the same talk multiple times (a conference circuit, a rehearsal, the real thing) and each run gets its own session.
| Field | Type | Notes |
|---|---|---|
| label | string | Auto-increments "Session 1", "Session 2"... renameable from the dashboard |
| started_at | datetime | Set when the session starts |
| ended_at | datetime | Nil while the session is active |
| talk_id | references | Parent talk |
See Talk sessions for how sessions get started and stopped.
reactions
One row per emoji tap, but only while a session is recording.
| Field | Type | Notes |
|---|---|---|
| emoji | string | The tapped emoji |
| slide_number | integer | Defaults to 0, meaning unknown or before the session started |
| talk_session_id | references | Deleted along with its session |
The full set the attendee can pick from, straight from talk_live.ex, is:
❤️ 😂 👏 🤯 🎉 😮 🎯 🔥 💡