How It Works
- Configure credentials in the dashboard — paste your APNs
.p8key, FCM service account JSON, or enable Web Push (keypair generated server-side). - Register devices — your client app calls
register()fromusePushRegistrationat a moment that makes sense for your UX (settings screen, first-run prompt, etc.). The SDK handles permission, token retrieval, and server registration. - Send notifications — your backend calls
sublay.push.send({ userIds, title, body, data }). Sublay fans the message out to every registered device for those users across all platforms.
Dashboard Setup
Installing the bundle
Open Database → Bundles in the dashboard and installpush. Once provisioning completes, the Push Notifications settings page becomes active.
Configuring providers
Go to Settings → Push Notifications in the dashboard. Configure each platform you want to support: APNs (iOS)| Field | Description |
|---|---|
| Key ID | The 10-character key identifier from your Apple Developer account |
| Team ID | Your Apple Developer team ID |
| Bundle ID | Your app’s bundle identifier (e.g. com.example.myapp) |
| .p8 key | Contents of the .p8 private key file downloaded from Apple |
| Production | Toggle for sandbox vs. production APNs gateway (defaults to production) |
GET /vapid-public-key endpoint for use in your service worker.
Test-send UI
Each provider card in the dashboard includes a Send Test Push panel. Supply a platform, a device token or subscription, a title, and a body, then click Send Test Push to verify credentials before shipping.Client SDK — Registering Devices
UseusePushRegistration with the adapter for your platform. Call register() in response to a deliberate user action — not on mount — because requesting OS push permission is a one-shot prompt that users cannot undo.
register(). See SDK Reference → Push Notifications for per-platform setup and usePushRegistration for the full hook API.
Server SDK — Sending Notifications
Callclient.push.send() from your backend whenever you want to notify users:
Rich Notification Payloads
Beyondtitle, body, and data, push.send() accepts optional fields for sound, badges, images, grouping, priority, and lifetime. Each maps to the native APNs / FCM / Web Push capability and is silently ignored on platforms that don’t support it — so you can set subtitle (iOS-only) and channelId (Android-only) in the same call without branching.
| Field | Platforms | Notes |
|---|---|---|
sound | iOS, Android, Web | Filename of a bundled sound. On Android 8+ the channel owns the sound — see below. |
badge | iOS | App-icon badge count. Your backend supplies the number; Sublay tracks no unread state. |
channelId | Android | Notification channel id. Created client-side. |
priority | iOS, Android | "high" (default) wakes the device; "normal" is power-considerate. |
subtitle | iOS | Line under the title. |
imageUrl | iOS, Android, Web | Big-picture image. iOS needs a Notification Service Extension — see below. |
tag | Android, Web | Display-replace key so notifications collapse instead of stacking. |
collapseId | iOS, Android | Transport-level collapse — a newer push supersedes an undelivered one. |
threadId | iOS | Notification grouping. |
ttl | iOS, Android | Time-to-live in seconds for offline devices. |
mutableContent | iOS | Enables your Notification Service Extension. Set automatically when imageUrl is present. |
Client-side requirements
Three of these need setup in your app — Sublay forwards the field but cannot do this part for you:Android sound → notification channels
Android sound → notification channels
On Android 8+ the notification channel owns the sound, importance, and vibration — the payload can’t override it. Create the channel once in your app (with the bundled sound) and pass its id as Then
channelId:push.send({ ..., channelId: "messages", sound: "notification.wav" }). The sound field alone is only a pre-Android-8 fallback. Sublay does not create channels for you.iOS images → Notification Service Extension
iOS images → Notification Service Extension
iOS does not download remote images from the payload on its own. To show
imageUrl on iOS, add a Notification Service Extension to your app that reads the URL from the notification payload, downloads it, and attaches it. Sublay sets mutable-content automatically whenever imageUrl is present so the extension is allowed to run. Android and Web render imageUrl with no extra work.Web rendering → your service worker
Web rendering → your service worker
Sublay ships no service worker — your app’s own SW renders web notifications. The server forwards the web-renderable fields (
sound, image, tag) in the push JSON; your push event handler decides how to display them via registration.showNotification(...).Device Lifecycle
- Re-registration: registering the same physical device again (same token or endpoint) updates the existing record instead of duplicating it.
- Device reassignment: if the same device is registered by a different user (e.g. a shared device after logout/login), the record is reassigned to the new user.
- Stale token cleanup: tokens or subscriptions permanently rejected by APNs, FCM, or Web Push during a send are automatically deleted — no separate cleanup pass is needed.
- Explicit logout: call
unregister()in your logout flow so the device stops receiving notifications after sign-out.
References
Everything related to push notifications across the docs:SDK Reference — Push Notifications
Per-platform client setup for Expo, React Native, and Web
usePushRegistration
Request permission, register, and unregister the current user’s device
Node SDK — Push Notifications
The
push.send() server module referenceWebhooks — Push Bridge
Forward
notification.created events to pushAPI Endpoints
Register Device
POST /push-notifications/devicesDeregister Device
DELETE /push-notifications/devicesSend Push
POST /push-notifications/sendGet VAPID Public Key
GET /push-notifications/vapid-public-key
