Pub/Sub
Publish custom named events to a channel. All subscribers receive them in real time. No server code required for basic pub/sub.
Channel naming
Use a path with a slash for custom channels. This bypasses ChangeTracker and uses pure WebSocket pub/sub:
const channel = realtime.channel('todos/shared-workspace')
// or:
const channel = realtime.channel('chat/general')
const channel = realtime.channel('game/room-42')Publish an event
channel.publish('todo:created', {
id: '123',
text: 'Buy groceries',
done: false,
})All other subscribers on todos/shared-workspace receive this event immediately.
Listen for events
channel
.on('todo:created', ({ data }) => {
setTodos(prev => [...prev, data])
})
.on('todo:toggled', ({ data }) => {
setTodos(prev => prev.map(t => t.id === data.id ? data : t))
})
.on('todo:deleted', ({ data }) => {
setTodos(prev => prev.filter(t => t.id !== data.id))
})
.subscribe()Avoid echo on your own events
Use a client ID to skip events you published yourself:
const clientId = useRef(Math.random().toString(36).slice(2))
channel.on('todo:created', ({ data, userId }) => {
if (userId === clientId.current) return // skip own event
setTodos(prev => [...prev, data])
})
// Pass your clientId so the server includes it in userId
channel.publish('todo:created', todo)Persist events for history
Pass { persist: true } to store the message in the database for later retrieval:
channel.publish('message', {
text: 'Hello everyone!',
userId: user.id,
}, { persist: true })Retrieve history with channel.getHistory() — see Message History.
Server-side pub/sub
Your Workers/Node.js server can also publish to channels:
// In your Worker handler
sdk.socket.emit('todo:created', newTodo, 'todos/shared-workspace')This is useful when you want to validate or transform data before broadcasting.
Complete example
import { useAerostack } from '@aerostack/react'
import { useEffect, useRef, useState } from 'react'
function CollaborativeList() {
const { realtime } = useAerostack()
const [items, setItems] = useState([])
const myId = useRef(Math.random().toString(36).slice(2))
const channelRef = useRef(null)
useEffect(() => {
const ch = realtime.channel('list/shared')
channelRef.current = ch
ch
.on('item:added', ({ data, userId }) => {
if (userId === myId.current) return
setItems(prev => [...prev, data])
})
.subscribe()
return () => ch.unsubscribe()
}, [realtime])
const addItem = (text) => {
const item = { id: Date.now(), text }
setItems(prev => [...prev, item]) // optimistic
channelRef.current.publish('item:added', item) // broadcast to peers
}
return (
<>
<button onClick={() => addItem('New item')}>Add</button>
<ul>{items.map(i => <li key={i.id}>{i.text}</li>)}</ul>
</>
)
}See the Collaborative Todos example for a complete working implementation with toggle, delete, and presence.