Chat rooms
Studio: Channels → Add rule: patternchat:*, Kind Presence, Subscribe and Publish Signed-in users, History depth 100, Message size limit 8192, Publish rate limit 5 per second.
App: subscribe to chat:<room>, load history(50), render, send("message", { text }). Show typing with send("typing"). Save messages you must keep to a messages table (the channel is a delivery layer, not storage).
Online users
Studio: same rule, Presence on. App: join with{ presence: { name } }, render presenceState(), listen to the presence event; group by user_id.
Notifications for one person
Studio: Add rule: patternuser:{{ auth.id }}, Kind Private, Subscribe Signed-in users, Publish Secret keys & Studio; Settings → Apps may publish off.
App: subscribe to user:<your id>; your server publishes (Publishing). Also write a notifications record so a missed message is still visible.
Per-organization feed
Studio: patternorg:{{ auth.org }}, Kind Presence, Subscribe and Publish Signed-in users.
App: after switchOrg("acme"), subscribe to org:acme. Re-subscribe on TOKEN_REFRESHED.
A live table
Studio: table → Settings → Behaviour → Broadcast changes on. App: Live records: load, then mergecreated / updated / deleted by id.
Collaborative cursors
Studio: patterndoc:*, Kind Presence, Publish rate limit 30 per second, Ephemeral (nothing kept).
App: send cursor events at most every 50 ms; render others’ cursors from from.
Order tracking
Studio: patternorder:*, Kind Protected (open to listen, only servers publish).
App: the customer subscribes to order:<id> and updates the status chip; your flow publishes status events as the order progresses.
A live admin dashboard
Studio: patternmetrics:*, Kind Protected, Subscribe role:admin.
App: use a stream (stream(["metrics:orders"])) so no socket is needed.
Design rules
Channel rules
The Studio form.
Troubleshooting
When it doesn’t work.