Skip to main content
Beyond the manual push.send() call, Sublay can automatically push in-app events (comments, mentions, follows, chat messages, …) to a user’s registered devices. This page covers the surfaces that control that automatic delivery:
  • Per-user preferences — each user can disable push for specific event types.
  • Per-conversation mute — a user can silence a single conversation’s push for a duration or forever.
  • Per-event copy templates & project-level toggles — the developer authors the push title/body per event type and can disable an event project-wide, from the dashboard.
Requires the push bundle. Automatic push and the preference table live in the push bundle. Install it from your project’s Database page in the dashboard. Chat-message push additionally requires the chat bundle; app-notification push requires the notifications bundle. See Bundles.

The event palette

Every automatic push is keyed by an event type. These are the server’s exact type names — the full app-notification set plus the chat message event (which is push-only and writes no in-app notification): entity-comment, comment-reply, entity-mention, comment-mention, entity-reaction, comment-reaction, entity-reaction-milestone-specific, entity-reaction-milestone-total, comment-reaction-milestone-specific, comment-reaction-milestone-total, new-follow, connection-request, connection-accepted, space-membership-approved, event-invite, event-updated, event-cancelled, message. The same names are used everywhere: a user’s disabledTypes, the project-level per-event toggle, and the template map all key on this exact list. The SDKs export the list as PUSH_EVENT_TYPES (@sublay/core, @sublay/node, @sublay/js).

Preference & mute model

Per-user preferences (disabledTypes)

Each user has at most one preference row, holding the set of event types they’ve opted out of for push. The model is:
  • Absence of a row = all-on. A user with no preference row receives push for every enabled event type. Reading preferences for such a user returns { "disabledTypes": [] }.
  • Updating replaces the set. The update endpoint upserts the whole disabledTypes array — send the complete set you want stored, not a delta.
  • Only valid type names are accepted. Unknown names are rejected server-side.
Disabling a type only suppresses push — the in-app App Notification is still written, so the bell/inbox is unaffected.

Per-conversation mute (mutedUntil / mutedForever)

A user can mute a single conversation for a fixed duration or forever. Mute suppresses the message push for that conversation only; the message is still delivered, socket-emitted, and available in the conversation as normal. The client sends a duration choice, never a raw timestamp — the server resolves the window from its own clock so client skew can’t distort it: Timed mutes expire lazily — once the window passes, push resumes with no user action.
“Forever” is an explicit signal, not a magic date. Internally the server stores “forever” as a far-future sentinel timestamp, but that value never reaches clients. At the API boundary the viewer’s own member row carries mutedForever: true with mutedUntil: null. Read the boolean — do not string-match a far-future date. The SDKs mirror this exactly.
The viewer’s own member row (currentMember) is serialized as:
Mute state is personal. A member’s mutedUntil / mutedForever is present only on that member’s own row. Endpoints that return other members’ rows (listMembers, changeMemberRole, addMember, the member:joined socket broadcast) omit both keys entirely — a user’s mute state is never exposed to other participants.

Gating precedence

When an event fires, whether a push is dispatched is decided in this order:
  1. Project-level event disable (dashboard toggle) — if the developer disabled the event, no one is pushed.
  2. Conversation mute (chat message only) — muted members are dropped.
  3. Per-user type toggle — users who disabled the type are dropped.
  4. Send to everyone remaining who has a registered device.

Copy templates & project-level toggles (dashboard)

The developer authors the push title/body copy per event type and can disable an event project-wide, from Settings → Push Notifications in the dashboard, beside the provider configuration.
  • Each event type has an editable template field and a project-level enable toggle.
  • A template is a plain-text string with {variableName} placeholders. Substitution is plain-text only — no expressions, no markup execution. Unknown tokens render empty.
  • If a project configures no template for an event, a shipped default is used. Template edits take effect on the next send.

Template variable palette

Each event exposes a fixed set of variables its template may interpolate. Values come from the notification metadata (app-notification events) or the message context (message). A token that isn’t in the event’s list renders empty. Example template for entity-comment:

Privacy

Muted-conversation content and disabled-type content is simply not dispatched — when a mute or a preference suppresses a push, the notification’s title/body (which for chat/comments contains a content snippet) is never sent to APNs, FCM, or Web Push at all. Suppression happens before any provider call, so muted/opted-out content never leaves Sublay’s infrastructure to a third-party push provider.

Building a settings UI

The SDKs expose the read/update primitives so you can build a notification-settings screen and per-conversation mute control:

useNotificationPreferences

Read + update the current user’s disabled types (React / RN / Expo)

useMuteConversation

Set / clear the current user’s conversation mute

Node SDK — Push Notifications

push.getNotificationPreferences / updateNotificationPreferences, chat.muteConversation

JS SDK — Push Notifications

push.getNotificationPreferences / updateNotificationPreferences, chat.muteConversation

API endpoints

Mute Conversation

POST /chat/conversations/:conversationId/mute

Get Notification Preferences

GET /push-notifications/preferences

Update Notification Preferences

PUT /push-notifications/preferences