Skip to content

Realtime Collaboration

Provider: Supabase Realtime
Protocol: WebSocket (via Supabase Channels)

How It Works

All project state changes are broadcast via Supabase Realtime. Multiple users editing the same project see changes in real time.

mermaid
graph LR
    A[Client A edits] --> B[PUT /api/projects/:id]
    B --> C[DB update]
    C --> D[Postgres trigger]
    D --> E[Supabase Realtime]
    E --> F[Client B receives]
    E --> G[Client C receives]

Channel Setup (Client)

svelte
<!-- src/routes/(app)/projects/[id]/+page.svelte -->
<script lang="ts">
  import { createClient } from '@supabase/supabase-js'
  import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'

  let { data } = $props()
  let project = $state(data.project)

  const supabase = createClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY)

  const channel = supabase
    .channel(`project:${data.project.id}`)
    .on('postgres_changes', {
      event: 'UPDATE',
      schema: 'public',
      table: 'projects',
      filter: `id=eq.${data.project.id}`
    }, (payload) => {
      project = payload.new
    })
    .subscribe()

  $effect(() => {
    return () => supabase.removeChannel(channel)
  })
</script>

Presence (Who's Online)

Show who else is currently viewing a project:

typescript
const presenceChannel = supabase.channel(`presence:${projectId}`)

presenceChannel
  .on('presence', { event: 'sync' }, () => {
    const state = presenceChannel.presenceState()
    onlineUsers = Object.values(state).flat()
  })
  .subscribe(async (status) => {
    if (status === 'SUBSCRIBED') {
      await presenceChannel.track({
        userId: user.id,
        name: user.name,
        joinedAt: new Date().toISOString()
      })
    }
  })

Conflict Resolution

Currently: last-write-wins at the field level. Future: operational transforms for concurrent text editing in Lexical.

Rate Limiting

Supabase Realtime is limited to:

  • 200 concurrent connections per project (free tier)
  • 10 messages/second per client

For larger agencies, upgrade to Pro or implement message batching.

Internal documentation for development team