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.
These are per-event-type controls for one signed-in user, and they are not the same thing as turning push off for an account on a device. A user with no disabled types still receives nothing on a device where their account has been silenced with useAccountPushToggle — that decides whether the account is bound to the device at all, while everything on this page decides which event types a bound account receives. The two compose, and neither overwrites the other.
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, reputation-grant, 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