Next

How to set up Supabase realtime subscriptions in Server Components?

November 28, 2025

download ready
Thank You
Your submission has been received.
We will be in touch and contact you soon!

Server Components handle initial data fetch; use Client Components with 'use client' for realtime subscriptions via supabase.channel().on('postgres_changes'). Enable RLS replication in Supabase dashboard. Merge server data as initial state, subscribe in useEffect for updates.

Example:-

Step 1: Install Dependencies

Code

npm install @supabase/supabase-js @supabase/ssr @supabase/auth-helpers-nextjs
      

Step 2: Environment Variables (.env.local)

Code

NEXT_PUBLIC_SUPABASE_URL=your_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
      

Step 3: Enable Replication (Supabase Dashboard)

Code

Database → Replication → Enable 'posts' table
      

Step 4: Server Component (Initial Data) - app/posts/page.tsx

Code

import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import RealtimePosts from './RealtimePosts';

export default async function PostsPage() {
  const supabase = createServerComponentClient({ cookies });
  const { data: initialPosts } = await supabase
    .from('posts')
    .select('*')
    .order('created_at', { ascending: false });

  return <RealtimePosts initialPosts={initialPosts || []} />;
}
      

Step 5: Client Component (Realtime) - app/posts/RealtimePosts.tsx

Code

'use client';
import { useEffect, useState } from 'react';
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

interface Post { id: string; title: string; created_at: string; }

export default function RealtimePosts({ initialPosts }: { initialPosts: Post[] }) {
  const [posts, setPosts] = useState(initialPosts);
  const supabase = createClientComponentClient();

  useEffect(() => {
    const channel = supabase
      .channel('posts')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'posts' }, 
        payload => payload.eventType === 'INSERT' 
          ? setPosts(p => [payload.new as Post, ...p])
          : setPosts(p => p.filter(post => post.id !== payload.new.id))
      )
      .subscribe();

    return () => supabase.removeChannel(channel);
  }, []);

  return (
    <div>
      {posts.map(post => (
        <div key={post.id} className="p-4 border-b">
          <h3>{post.title}</h3>
          <p>{new Date(post.created_at).toLocaleString()}</p>
        </div>
      ))}
    </div>
  );
}
      

Step 6: Test Realtime

Create/update posts in Supabase dashboard updates appear instantly without refresh.

Hire Now!

Need Help with Next Development ?

Work with our skilled next developers to accelerate your project and boost its performance.
**Hire now**Hire Now**Hire Now**Hire now**Hire now

How to set up Supabase realtime subscriptions in Server Components?

Server Components handle initial data fetch; use Client Components with 'use client' for realtime subscriptions via supabase.channel().on('postgres_changes'). Enable RLS replication in Supabase dashboard. Merge server data as initial state, subscribe in useEffect for updates.

Example:-

Step 1: Install Dependencies

Code

npm install @supabase/supabase-js @supabase/ssr @supabase/auth-helpers-nextjs
      

Step 2: Environment Variables (.env.local)

Code

NEXT_PUBLIC_SUPABASE_URL=your_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
      

Step 3: Enable Replication (Supabase Dashboard)

Code

Database → Replication → Enable 'posts' table
      

Step 4: Server Component (Initial Data) - app/posts/page.tsx

Code

import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import RealtimePosts from './RealtimePosts';

export default async function PostsPage() {
  const supabase = createServerComponentClient({ cookies });
  const { data: initialPosts } = await supabase
    .from('posts')
    .select('*')
    .order('created_at', { ascending: false });

  return <RealtimePosts initialPosts={initialPosts || []} />;
}
      

Step 5: Client Component (Realtime) - app/posts/RealtimePosts.tsx

Code

'use client';
import { useEffect, useState } from 'react';
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

interface Post { id: string; title: string; created_at: string; }

export default function RealtimePosts({ initialPosts }: { initialPosts: Post[] }) {
  const [posts, setPosts] = useState(initialPosts);
  const supabase = createClientComponentClient();

  useEffect(() => {
    const channel = supabase
      .channel('posts')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'posts' }, 
        payload => payload.eventType === 'INSERT' 
          ? setPosts(p => [payload.new as Post, ...p])
          : setPosts(p => p.filter(post => post.id !== payload.new.id))
      )
      .subscribe();

    return () => supabase.removeChannel(channel);
  }, []);

  return (
    <div>
      {posts.map(post => (
        <div key={post.id} className="p-4 border-b">
          <h3>{post.title}</h3>
          <p>{new Date(post.created_at).toLocaleString()}</p>
        </div>
      ))}
    </div>
  );
}
      

Step 6: Test Realtime

Create/update posts in Supabase dashboard updates appear instantly without refresh.