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.