Messaging reference
Public channels, messages, reactions, members, and read receipts.
On this page
The messaging API is an app-owned, public-chat layer. Add the five messaging schemas to your RecordRoom, then import the hooks from deepspace.
import {
useChannels,
useMessages,
useReactions,
useChannelMembers,
useReadReceipts,
} from 'deepspace'
Each hook returns status: 'loading' | 'ready' | 'error' and error?: string with its records. The SDK does not include a global conversation or directory service.
useChannels()#
function useChannels(): {
channels: RecordData<Channel>[]
status: 'loading' | 'ready' | 'error'
error?: string
create: (input: { name: string; description?: string }) => Promise<string>
update: (channelId: string, patch: Partial<Pick<Channel, 'name' | 'description'>>) => void
archive: (channelId: string) => void
remove: (channelId: string) => Promise<void>
}
create always writes type: 'public'. update, archive, and remove are fire-and-forget. The remove promise resolves after the client sends the request, before the room answers; handle a room refusal with RecordProvider.onWriteError.
const { create, archive } = useChannels()
const channelId = await create({ name: 'general', description: 'Announcements' })
archive(channelId)
useMessages(channelId, options?)#
function useMessages(
channelId: string | undefined,
options?: { parentMessageId?: string },
): {
messages: RecordData<Message>[]
status: 'loading' | 'ready' | 'error'
error?: string
send: (content: string, parentMessageId?: string) => Promise<string> | undefined
edit: (messageId: string, newContent: string) => void
softDelete: (messageId: string) => void
remove: (messageId: string) => void
}
send returns the new ID, or undefined without both a channel and signed-in user. edit, softDelete, and remove are fire-and-forget. Use softDelete for user-facing deletion so reply relationships remain intact. Pass options.parentMessageId to query one reply thread.
const { messages, send } = useMessages(channelId)
await send('Hello')
await send('A reply', parentMessageId)
useReactions(channelId)#
type GroupedReaction = {
emoji: string
count: number
currentUserReacted: boolean
userIds: string[]
}
function useReactions(channelId: string | undefined): {
reactions: RecordData<Reaction>[]
status: 'loading' | 'ready' | 'error'
error?: string
getReactionsForMessage: (messageId: string) => GroupedReaction[]
toggle: (messageId: string, emoji: string) => void
}
toggle is fire-and-forget. The schema's uniqueness constraint prevents duplicate (messageId, emoji, userId) rows.
useChannelMembers(channelId)#
function useChannelMembers(channelId: string | undefined): {
members: RecordData<ChannelMember>[]
status: 'loading' | 'ready' | 'error'
error?: string
join: () => Promise<void>
leave: () => Promise<void>
isMember: boolean
}
join and leave use confirmed mutations. They resolve after acceptance and reject on failure. Membership is an opt-in signal for public channels; it does not restrict who can read messages.
useReadReceipts()#
function useReadReceipts(): {
receipts: RecordData<ReadReceipt>[]
status: 'loading' | 'ready' | 'error'
error?: string
markAsRead: (channelId: string) => void
getUnreadCount: (channelId: string, messages: RecordData<Message>[]) => number
}
markAsRead is fire-and-forget and stores the current timestamp. getUnreadCount compares message creation times with that timestamp.
Record types#
interface Channel {
name: string
description?: string
type: 'public'
createdBy: string
archived: boolean
}
interface Message {
channelId: string
content: string
authorId: string
parentMessageId?: string
edited: boolean
editedAt?: string
deleted?: boolean
}
interface Reaction {
messageId: string
channelId: string
emoji: string
userId: string
}
interface ChannelMember {
channelId: string
userId: string
joinedAt: string
}
interface ReadReceipt {
channelId: string
userId: string
lastReadAt: string
}
Each value is wrapped in the standard record envelope (recordId, data, createdBy, createdAt, updatedAt).
See also#
- Messaging guide — worked public-chat UI.
- Permissions — app-specific participant access.
- Schemas reference — collection definitions and RBAC.