Realtime

Channels

Channels allow you to scope events to specific people or rooms. For example:

  • Chat rooms
  • Emitting events to a specific user

Default Channel

By default, events are sent to the default channel. If we emit an event without specifying a channel like so:

await realtime.emit("notification.alert", "hello world!")

it can automatically be read using the default channel:

useRealtime({  events: ["notification.alert"],  onData({ event, data, channel }) {    console.log(data)  },})

Custom Channels

Emit events to a specific channel:

route.ts
const channel = realtime.channel("user-123")await channel.emit("notification.alert", "hello world!")

Subscribe to one or more channels:

page.tsx
"use client"import { useRealtime } from "@/lib/realtime-client"export default function Page() {  useRealtime({    channels: ["user-123"],    events: ["notification.alert"],    onData({ event, data, channel }) {      console.log(data)    },  })  return <>...</>}

Channel Patterns

User-Specific Channels

Send notifications to individual users:

route.ts
const channel = realtime.channel(`user-${userId}`)await channel.emit("notification.alert", "hello world!")
page.tsx
useRealtime({  channels: [`user-${user.id}`],  events: ["notification.alert"],  onData({ data }) {},})
Room-Based Channels

Broadcast to all users in a room:

route.ts
await realtime.channel(`room-${roomId}`).emit("room.message", {  text: "Hello everyone!",  sender: "Alice",})
Team Workspaces

Scope events to team workspaces:

route.ts
await realtime.channel(`team-${teamId}`).emit("project.update", {  project: "Website Redesign",  status: "In Progress",})

Dynamic Channels

Subscribe to multiple channels at the same time:

page.tsx
"use client"import { useState } from "react"import { useRealtime } from "@/lib/realtime-client"export default function Page() {  const [channels, setChannels] = useState<string[]>(["lobby"])  useRealtime({    channels,    events: ["chat.message"],    onData({ event, data, channel }) {      console.log(`Message from ${channel}:`, data)    },  })  const joinRoom = (roomId: string) => {    setChannels((prev) => [...prev, roomId])  }  const leaveRoom = (roomId: string) => {    setChannels((prev) => prev.filter((c) => c !== roomId))  }  return (    <div>      <p>Active channels: {channels.join(", ")}</p>      <button onClick={() => joinRoom("room-1")}>Join Room 1</button>      <button onClick={() => joinRoom("room-2")}>Join Room 2</button>      <button onClick={() => leaveRoom("lobby")}>Leave Lobby</button>    </div>  )}

Broadcasting to Multiple Channels

Emit to multiple channels at the same time:

route.ts
const rooms = ["lobby", "room-1", "room-2"]await Promise.all(  rooms.map((room) => {    const channel = realtime.channel(room)    return channel.emit("chat.message", `Hi channel ${room}!`)  }))

Channel Security

Combine channels with middleware for secure access control:

app/api/realtime/route.ts
import { handle } from "@upstash/realtime"import { realtime } from "@/lib/realtime"import { currentUser } from "@/auth"export const GET = handle({  realtime,  middleware: async ({ request, channels }) => {    const user = await currentUser(request)    for (const channel of channels) {      if (!user.canAccessChannel(channel)) {        return new Response("Unauthorized", { status: 401 })      }    }  },})
Authenticate Realtime Requests

See the middleware documentation for authentication examples

Loading search…