---
title: Notify SDK
description: Real-time notifications with channels, read/unread tracking, and badge counts.
---

# @nolag/notify

Real-time notifications with channels, read/unread tracking, and badge counts.

## Overview

`@nolag/notify` delivers real-time notifications to your users with full read/unread lifecycle management. Notifications are organised into channels (logical groupings like `'alerts'`, `'mentions'`, or `'system'`) and each channel tracks its own unread count independently. The SDK replays up to 30 days of notification history on reconnect so users never miss an event regardless of when they were last online.

### Key Features

- Channel-based notification delivery with independent unread counts
- 30-day notification replay so users catch up after any period offline
- Per-notification and bulk read/unread tracking
- Global badge counts aggregated across all subscribed channels
- Rich notification payloads with title, body, icon, actions, and custom data
- Automatic reconnection with channel restoration

## How It Works

`NoLagNotify` wraps the `@nolag/js-sdk` client. Each channel you subscribe to creates a `NotifyChannel` instance that subscribes to two topics: `notifications` for durable notification delivery and `_read` for ephemeral read-receipt signals. A `NotificationStore` inside each channel accumulates notifications and tracks read state, while the main class aggregates badge counts across all channels.

| Topic | Purpose | Replay |
| --- | --- | --- |
| `notifications` | Notification payloads: title, body, icon, actions, and custom data | 30 days |
| `_read` | Read receipt signals (ephemeral) | None |

## Installation

```bash [Terminal]
npm install @nolag/notify @nolag/js-sdk
```

## Quick Start

```typescript [TypeScript]
import { NoLagNotify } from '@nolag/notify'

// Create and connect the client
const notify = new NoLagNotify('your-access-token', {
  user: { id: 'user-123', name: 'Alice' },
})

await notify.connect()

// Subscribe to a notification channel
const channel = await notify.subscribe('alerts')

// Listen for new notifications
channel.on('notification', (n) => {
  console.log(`[${n.title}]: ${n.body}`)
  console.log('Unread:', channel.getUnread().length)
})

// Mark a specific notification as read
await channel.markRead(n.id)

// Mark everything in the channel as read
await channel.markAllRead()

// Get global badge counts across all channels
const badges = notify.getBadgeCounts()
console.log('Total unread:', badges.total)

// Mark all channels read at once
await notify.markAllRead()

notify.disconnect()
```

## API Reference

### NoLagNotify

The main class. Manages the WebSocket connection, channel subscriptions, and global badge counts.

| Method | Description |
| --- | --- |
| `connect()` | Establish WebSocket connection |
| `disconnect()` | Gracefully close the connection and clear all channels |
| `subscribe(channel)` | Subscribe to a notification channel; returns a `NotifyChannel` instance |
| `unsubscribe(channel)` | Unsubscribe from a channel and remove it from badge tracking |
| `getBadgeCounts()` | Return unread counts for every subscribed channel plus a `total` aggregate |
| `markAllRead()` | Mark all notifications across all subscribed channels as read |

### Events: NoLagNotify

| Event | Payload | Description |
| --- | --- | --- |
| `connected` | none | WebSocket connection established |
| `disconnected` | `reason: string` | Connection closed |
| `reconnected` | none | Reconnection successful; channels are restored automatically |
| `error` | `error: Error` | Unrecoverable error occurred |
| `notification` | `{ channel: string, notification: Notification }` | A new notification arrived on any subscribed channel |
| `badgeUpdated` | `{ channel: string, count: number, total: number }` | Badge counts changed for a channel |

### NotifyChannel

Returned by `subscribe()`. Scoped to a single channel; handles notification delivery, storage, and read state.

| Method | Description |
| --- | --- |
| `send(title, opts)` | Publish a notification to this channel (typically called server-side) |
| `markRead(id)` | Mark a single notification as read by ID |
| `markAllRead()` | Mark every notification in this channel as read |
| `getNotifications()` | Return all notifications in the local store |
| `getUnread()` | Return only unread notifications |

### Events: NotifyChannel

| Event | Payload | Description |
| --- | --- | --- |
| `notification` | `Notification` | A new notification arrived on this channel |
| `read` | `{ id: string }` | A notification was marked as read |
| `readAll` | none | All notifications in this channel were marked as read |
| `replayStart` | `{ count: number }` | Historical notification replay is beginning |
| `replayEnd` | `{ replayed: number }` | Historical notification replay is complete |
