realtime pattern

Chat — thread

Active conversation view — message list + composer.

When to use it

User selects a conversation. Right pane on desktop, full screen on mobile.

  • Smooth scroll-to-bottom on new message
  • Edit own messages within 5 minutes
  • Reactions in 2 taps

Layout regions

  • header
  • messages
  • composer

States

  • default
  • loading
  • empty
  • partial

Example

Next.js — Server Component shell + client-side WS thread

// app/chat/[id]/page.tsx — Server Component
import { fetchThread } from '@/lib/api.server'
import { ChatThreadClient } from './chat-thread-client'

export default async function ChatPage({ params }) {
  const initial = await fetchThread((await params).id)
  return <ChatThreadClient threadId={initial.id} initial={initial} />
}

// chat-thread-client.tsx
'use client'
import { useEffect, useRef, useState } from 'react'
import useWebSocket from 'react-use-websocket'

export function ChatThreadClient({ threadId, initial }) {
  const [messages, setMessages] = useState(initial.messages)
  const scrollRef = useRef<HTMLDivElement>(null)
  const { sendJsonMessage } = useWebSocket('wss://api.brand.com/chat', {
    onMessage: (e) => setMessages((m) => [...m, JSON.parse(e.data)]),
    shouldReconnect: () => true,
  })
  useEffect(() => {
    const el = scrollRef.current
    if (el && el.scrollTop + el.clientHeight > el.scrollHeight - 200) {
      el.scrollTop = el.scrollHeight
    }
  }, [messages.length])

  return (
    <Stack className="h-full">
      <ChatHeader />
      <ScrollArea ref={scrollRef} className="flex-1" role="log" aria-live="polite">
        <Stack size="2">{messages.map((m) => <Bubble key={m.id} {...m} />)}</Stack>
      </ScrollArea>
      <Composer onSubmit={(text) => sendJsonMessage({ threadId, text })} />
    </Stack>
  )
}

The full Chat — thread pattern specifies 3 exact microcopy strings, 2 motion specs, 5 composition rules, 2 more code examples — all gated behind the full recipe. Get the full recipe.

Build the Chat — thread pattern in your project.