Recipes

Real-Time Feed

Build a feed/chat UI with paginated queries and optimistic inserts.

Goal

Render a live-updating list and prepend optimistic items instantly.

<script setup lang="ts">
import { api } from '~~/convex/_generated/api'

const message = ref('')

const { results, status, loadMore, isLoading } = await useConvexPaginatedQuery(
  api.messages.listPaginated,
  {},
  {
    initialNumItems: 20,
  },
)

const { execute: sendMessage, pending } = useConvexMutation(api.messages.send, {
  optimisticUpdate: (localStore, args) => {
    insertAtTop({
      query: api.messages.listPaginated,
      store: localStore,
      item: {
        _id: crypto.randomUUID(),
        _creationTime: Date.now(),
        text: args.text,
        authorName: 'You',
      },
    })
  },
})

async function submit() {
  if (!message.value.trim()) return
  await sendMessage({ text: message.value })
  message.value = ''
}
</script>

Notes

  • Keep optimistic items minimal and shape-compatible with your query result.
  • Prefer insertAtTop for chat/feed timelines and insertAtBottomIfLoaded for append-heavy lists.
  • Use status / isLoading to render loading states without extra refs.