smithery.ai

supabase-realtime

Comprehensive guide for implementing Supabase Realtime features with best practices, scalable patterns, and migration strategies.

First seen Mar 25, 2026

Installation

$ npx skills add https://smithery.ai

Summary

  • Comprehensive guide for implementing Supabase Realtime features with best practices, scalable patterns, and migration strategies.
  • Use when building realtime features in Supabase applications including messaging, notifications, presence, live updates, collaborative features, or migrating from postgres_changes to broadcast.
  • Covers client setup, database triggers with realtime.broadcast_changes, RLS authorization, naming conventions, and performance optimization.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,083 B
  • docs SUMMARY.md 489 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Supabase Realtime

Expert implementation guide for Supabase Realtime features focusing on scalable patterns and best practices.

Core Principles

Always use broadcast over postgreschanges - postgreschanges is single-threaded and doesn't scale. Use broadcast with database triggers for all database change notifications.

Use dedicated topics - Never broadcast to global topics. Use granular patterns like room:123:messages, user:456:notifications.

Private channels by default - Set private: true for all database-triggered channels. Enable private-only mode in production.

Quick Reference

Naming Conventions

  • Topics: scope:entity:id (e.g., room:123:messages)
  • Events: entityaction in snakecase (e.g., message_created)

Client Setup Pattern

const channel = supabase.channel('room:123:messages', {
  config: {
    broadcast: { self: true, ack: true },
    private: true  // Required for RLS
  }
})

// Set auth before subscribing
await supabase.realtime.setAuth()

channel
  .on('broadcast', { event: 'message_created' }, handler)
  .subscribe((status, err) => {
    if (status === 'SUBSCRIBED') console.log('Connected')
  })

// Cleanup
supabase.removeChannel(channel)

Database Trigger Pattern

-- Use realtime.broadcast_changes for database events
CREATE OR REPLACE FUNCTION notify_table_changes()
RETURNS TRIGGER AS $$
BEGIN
  PERFORM realtime.broadcast_changes(
    TG_TABLE_NAME || ':' || COALESCE(NEW.id, OLD.id)::text,
    TG_OP,
    TG_OP,
    TG_TABLE_NAME,
    TG_TABLE_SCHEMA,
    NEW,
    OLD
  );
  RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER messages_broadcast_trigger
  AFTER INSERT OR UPDATE OR DELETE ON messages
  FOR EACH ROW EXECUTE FUNCTION notify_table_changes();

RLS Authorization

-- Required for private channels
CREATE POLICY "room_members_can_read" ON realtime.messages
FOR SELECT TO authenticated
USING (
  topic LIKE 'room:%' AND
  EXISTS (
    SELECT 1 FROM room_members
    WHERE user_id = auth.uid()
    AND room_id = SPLIT_PART(topic, ':', 2)::uuid
  )
);

-- Required index for performance
CREATE INDEX idx_room_members_user_room ON room_members(user_id, room_id);

Implementation Checklist

  • Use broadcast not postgres_changes
  • Dedicated topics per room/user/entity
  • Set private: true for database triggers
  • Create indexes for all RLS policy columns
  • Include cleanup/unsubscribe logic
  • Check channel state before subscribing
  • Use consistent naming conventions

Use Cases for cv-optimizer

User Notifications

// Notify user when CV optimization is complete
const channel = supabase.channel(`user:${userId}:notifications`, {
  config: { private: true }
})

channel
  .on('broadcast', { event: 'optimization_complete' }, (payload) => {
    // Show notification to user
    toast.success('Your CV has been optimized!')
  })
  .subscribe()

Live Progress Updates

// Real-time progress during CV optimization
const channel = supabase.channel(`job:${jobId}:progress`, {
  config: { private: true }
})

channel
  .on('broadcast', { event: 'progress_update' }, (payload) => {
    setProgress(payload.percentage)
  })
  .subscribe()

Best Practices

  1. Always clean up channels when component unmounts
  2. Use private channels for user-specific data
  3. Index RLS policy columns for performance
  4. Prefer broadcast over postgres_changes for scalability
  5. Use granular topic naming for fine-grained subscriptions