Skip to content

WebSocket Gateway

Next.js Backend supports WebSocket communication through the @WebSocketGateway decorator, providing a NestJS-compatible gateway pattern powered by Elysia's native WebSocket.

Creating a Gateway

typescript
import {
  WebSocketGateway,
  OnMessage,
  OnOpen,
  OnClose,
  WebSocketServer,
  type WsContext,
} from 'next-js-backend';

@WebSocketGateway('/chat')
export class ChatGateway {
  @OnOpen()
  onOpen(ctx: WsContext) {
    Logger.log('Client connected:', ctx.id);
    ctx.send(JSON.stringify({ event: 'welcome', data: 'Connected!' }));
  }

  @OnMessage()
  onMessage(ctx: WsContext, message: string | Buffer) {
    const data = JSON.parse(message.toString());
    Logger.log('Received:', data);

    // Echo back
    ctx.send(JSON.stringify({ event: 'echo', data }));
  }

  @OnClose()
  onClose(ctx: WsContext) {
    Logger.log('Client disconnected:', ctx.id);
  }
}

Registering the Gateway

Add to your module's providers:

typescript
@Module({
  providers: [ChatGateway],
})
export class ChatModule {}

Rooms / Broadcasting

typescript
@WebSocketGateway('/chat')
export class ChatGateway {
  private rooms = new Map<string, Set<WsContext>>();

  @OnMessage()
  onMessage(ctx: WsContext, message: string) {
    const { event, room, data } = JSON.parse(message);

    if (event === 'join') {
      if (!this.rooms.has(room)) this.rooms.set(room, new Set());
      this.rooms.get(room)!.add(ctx);
    }

    if (event === 'broadcast') {
      const roomClients = this.rooms.get(room) ?? new Set();
      for (const client of roomClients) {
        client.send(JSON.stringify({ event: 'message', data }));
      }
    }
  }

  @OnClose()
  onClose(ctx: WsContext) {
    // Remove from all rooms
    for (const clients of this.rooms.values()) {
      clients.delete(ctx);
    }
  }
}

Client Connection

javascript
const ws = new WebSocket('ws://localhost:3000/chat');

ws.onopen = () => {
  ws.send(JSON.stringify({ event: 'join', room: 'general' }));
};

ws.onmessage = ({ data }) => {
  Logger.log(JSON.parse(data));
};

Released under the MIT License.