Broadcast
Push notifications to the browser in real time over socket.io. Each notifiable gets its own room; pair it with the database channel for a live in-app feed.
The broadcast channel pushes a notification to connected clients in real time over socket.io. It emits an event into a per-notifiable room, so a user sees the notification land without polling. It pairs naturally with the database channel — persist for the feed, broadcast for the live update.
Install
The channel uses Nest's websockets layer and socket.io, so install those peers alongside it:
pnpm add @dudousxd/nestjs-notifications-broadcast @nestjs/websockets @nestjs/platform-socket.io socket.ionpm install @dudousxd/nestjs-notifications-broadcast @nestjs/websockets @nestjs/platform-socket.io socket.ioRegister the channel
import { BroadcastChannelModule } from '@dudousxd/nestjs-notifications-broadcast';
@Module({
imports: [
BroadcastChannelModule.forRoot({ event: 'notification', namespace: '/ws' }),
],
})
export class AppModule {}BroadcastChannelModule.forRoot() takes:
| Option | Type | Default | Description |
|---|---|---|---|
event | string | 'notification' | The socket.io event name emitted to clients. |
namespace | string | — | socket.io namespace to mount the gateway on. |
global | boolean | true | Register globally so the channel is discoverable app-wide. |
Registering the module also stands up a NotificationsGateway — the socket.io gateway that holds
the server reference and emits into rooms. It's exported, so you can inject it to have clients join
their room on connect (typically keyed by the same value you route on).
The notification side
Annotate the payload method with the @Broadcast() handle and return the real-time payload:
import { type Notifiable, Notification } from '@dudousxd/nestjs-notifications-core';
import { Broadcast } from '@dudousxd/nestjs-notifications-broadcast';
@Notification()
export class InvoicePaid {
constructor(private invoiceId: string) {}
@Broadcast()
toBroadcast({ notifiable }: ChannelContext): Record<string, unknown> {
return { invoiceId: this.invoiceId, message: 'Your invoice was paid' };
}
}The Broadcast handle also works as a via() token (via() { return [Broadcast]; }) for
explicit routing; implement
BroadcastNotification alongside the decorator for compile-time checks.
toBroadcast() is optional when you route with an explicit via(). If it's absent the channel
falls back to toArray(), and finally to a structural copy of the notification's own properties.
The target room
The room comes from the notifiable's routeNotificationFor('broadcast') — return the room name the
client joined:
export class User implements Notifiable {
constructor(public id: number) {}
routeNotificationFor(channel: string) {
if (channel === 'broadcast') return `user.${this.id}`;
return undefined;
}
}The channel emits the configured event with the payload to every client in that room.
Broadcast is fire-and-forget: there's no persistence, so a client offline at send time misses the
event. Add the database channel to the same via() so the notification
is also stored — the live push updates the UI now, the stored row backs the feed on next load.
Database
Persist notifications so you can show an in-app feed. A NotificationStore interface, a bundled in-memory store, and TypeORM / MikroORM / Prisma adapters.
Slack
Post notifications to Slack via an incoming webhook or the Web API. A fluent SlackMessage builder with text, Block Kit blocks, and attachments.