Skip to main content

Realtime Chat

A complete chat application with rooms, usernames, and typing indicators using RealtimeNamespace.

Overview

This example builds a multi-room chat where clients can:

  • Connect with a username
  • Join and leave rooms
  • Send messages to a room
  • See typing indicators
  • Receive join/leave notifications

Function Code

const ns = new RealtimeNamespace('/chat')

ns.socket.on('$connect', async function () {
const username = ns.socket.handshake.auth.username || 'Anonymous'
await kv.set(`${ns.socket.id}:username`, username)
await kv.set(`${ns.socket.id}:currentRoom`, null)
ns.socket.emit('welcome', { message: `Welcome, ${username}!`, socketId: ns.socket.id })
})

ns.socket.on('joinRoom', async function (data) {
if (!data || typeof data.room !== 'string') return
const room = data.room
const currentRoom = await kv.get(`${ns.socket.id}:currentRoom`)
const username = await kv.get(`${ns.socket.id}:username`)
if (currentRoom) {
ns.socket.to(currentRoom).emit('userLeft', { username })
ns.socket.leave(currentRoom)
}
ns.socket.join(room)
await kv.set(`${ns.socket.id}:currentRoom`, room)
ns.socket.to(room).emit('userJoined', { username })
ns.socket.emit('joinedRoom', { room })
})

ns.socket.on('message', async function (data) {
const room = await kv.get(`${ns.socket.id}:currentRoom`)
const username = await kv.get(`${ns.socket.id}:username`)
if (!room || !data?.text) return
ns.to(room).emit('message', {
username,
text: data.text,
timestamp: Date.now(),
id: crypto.randomUUID()
})
})

ns.socket.on('$disconnect', async function () {
const room = await kv.get(`${ns.socket.id}:currentRoom`)
const username = await kv.get(`${ns.socket.id}:username`)
if (room) ns.socket.to(room).emit('userLeft', { username })
await kv.delete(`${ns.socket.id}:username`)
await kv.delete(`${ns.socket.id}:currentRoom`)
})

export default ns