Most web apps are solitary by default.
You open a tab, click a form, submit data—yet you never see who else is there.
That isn’t a web limitation; it’s a design limitation.
Phoenix LiveView breaks the mold.
With Phoenix Presence + PubSub, you can make any interface:
- Social
- Alive
- Aware
What Presence Really Is
Presence is awareness — not analytics.
- See who joins a chat room
- Know who’s editing a document
- Show “currently viewing” badges
- Render typing indicators, collaborative cursors, and more
It surfaces real‑time context that builds trust.
How Presence Works (High‑Level)
- Client connects to a LiveView
- LiveView subscribes to a topic:
Phoenix.PubSub.subscribe(MyApp.PubSub, "client:123")
- Track the user:
Phoenix.Presence.track( self(), # LiveView PID "client:123", # topic user.id, # unique key %{name: user.name, avatar: user.avatar_url} )
- Presence diff is broadcast automatically
- Every client renders updates immediately (no polling)
Example: Real‑Time CRM Editing
# In mount/3 topic = "client:#{client.id}" Phoenix.PubSub.subscribe(MyApp.PubSub, topic) Phoenix.Presence.track( self(), topic, user.id, %{name: user.name} ) # In handle_info for presence diffs def handle_info(%{event: "presence_diff"} = msg, socket) do users = MyPresence.list(socket.assigns.topic) {:noreply, assign(socket, users: users)} end
Now you can render:
<ul> <%= for {_id, %{metas: [meta]}} <- @users do %> <li><%= meta.name %> is here</li> <% end %> </ul>
No polling. No extra JavaScript. Pure LiveView.
Why Presence Scales
- Diff‑based updates → minimal payloads
- Tracker keeps memory low across nodes
- Built for distributed clusters
- Works with millions of presence events
Enhancing UX with Presence Metadata
Idea | How to Track |
---|---|
Join time | %{joined_at: DateTime.utc_now()} |
Idle status (2 min) | Client‑side hook updates idle: true |
Custom avatar changes | Update %{avatar_url: ...} |
Your LiveView reacts in handle_info
and re‑renders instantly.
Pattern: Store Presence in Assigns
def handle_info(%{event: "presence_diff"}, socket) do users = MyPresence.list(socket.assigns.topic) {:noreply, assign(socket, :users, users)} end
UI latency is near‑zero.
The client simply reacts to truth.
Design Philosophy
Presence isn’t just a feature.
“Make state visible. Reflect it fast. Let users feel the other people in the room.”
No extra APIs, no polling, no hacks—just:
- Topic namespace
- Track + diff
- Render the truth
Ready for More?
If you’re serious about Phoenix LiveView, download my PDF:
Phoenix LiveView: The Pro’s Guide to Scalable Interfaces and UI Patterns
- Collaborative tools
- Real‑time dashboards
- Presence patterns
- Production‑grade advice
Make your LiveView apps more powerful, usable, and real.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.