Chat
RTCstack uses LiveKit's data channel for real-time chat. Messages are sent to all participants (or optionally, a subset).
Sending Messages
ts
// Broadcast to all participants
await call.sendMessage('Hello everyone!')
// Send to specific participants
await call.sendMessage('Hey Alice', { to: ['user-alice-identity'] })Receiving Messages
ts
call.on('messageReceived', (message) => {
console.log(message.from, ':', message.text)
})Message Shape
ts
interface Message {
id: string // UUID
from: string // sender identity (userId from token)
text: string
timestamp: Date
to?: string[] // undefined = broadcast
}Message History
The last 500 messages are kept in memory:
ts
call.messages // Message[]Messages are not persisted beyond the call session. If you need message history across sessions, store them in your own database using the messageReceived event.
Reactions
Reactions are emoji sent over the same data channel:
ts
await call.sendReaction('👏')
call.on('reactionReceived', (from, emoji) => {
showFloatingEmoji(emoji, from)
})Reactions are not stored in call.messages — they're ephemeral display events.
React
tsx
import { useMemo, useState } from 'react'
import { useMessages, useCall } from '@rtcstack/ui-react'
function Chat() {
const messages = useMessages()
const call = useCall()
const [text, setText] = useState('')
return (
<div>
{messages.map(m => (
<div key={m.id}><strong>{m.from}:</strong> {m.text}</div>
))}
<input value={text} onChange={e => setText(e.target.value)} />
<button onClick={() => { call.sendMessage(text); setText('') }}>Send</button>
</div>
)
}Or use the pre-built <ChatPanel /> component which includes auto-scroll, Ctrl+Enter send, and aria-live announcements.
Vue 3
vue
<script setup>
import { ref } from 'vue'
import { useMessages, useCall } from '@rtcstack/ui-vue'
const messages = useMessages()
const call = useCall()
const text = ref('')
function send() {
call.sendMessage(text.value)
text.value = ''
}
</script>
