supabase

git-tao's avatarfrom git-tao

Supabase open-source Firebase alternative with PostgreSQL database, authentication, storage, real-time subscriptions, and edge functions

0stars🔀0forks📁View on GitHub🕐Updated Jan 9, 2026

When & Why to Use This Skill

This Claude skill provides comprehensive assistance for developing with Supabase, the leading open-source Firebase alternative. It enables developers to efficiently manage PostgreSQL databases, implement robust authentication, handle cloud storage, and integrate real-time subscriptions into their applications using best practices and optimized code snippets.

Use Cases

  • Building full-stack web and mobile applications by leveraging Supabase as a scalable Backend-as-a-Service (BaaS).
  • Implementing secure user authentication and fine-grained access control using Row Level Security (RLS) policies.
  • Executing complex PostgreSQL database operations, including relational queries, advanced filtering, and data mutations.
  • Developing real-time features such as live chat, notifications, or collaborative dashboards using database subscriptions.
  • Automating backend workflows with serverless Edge Functions and managing infrastructure via the Supabase CLI.
namesupabase
descriptionSupabase open-source Firebase alternative with PostgreSQL database, authentication, storage, real-time subscriptions, and edge functions

Supabase Skill

Comprehensive assistance with Supabase development - the open-source Firebase alternative with PostgreSQL database, Auth, Storage, Realtime, and Edge Functions.

When to Use This Skill

This skill should be triggered when:

  • Working with Supabase database, auth, storage, or realtime
  • Building full-stack applications with PostgreSQL
  • Implementing user authentication and authorization
  • Working with Row Level Security (RLS)
  • Building real-time features with subscriptions
  • Deploying Edge Functions (Deno)
  • Using Supabase with React, Next.js, Vue, Flutter, etc.

Quick Reference

Initialize Supabase Client (JavaScript)

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  'https://your-project.supabase.co',
  'your-anon-key'
)

Initialize for Server-Side (Next.js)

import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)
          )
        },
      },
    }
  )
}

Authentication

// Sign up
const { data, error } = await supabase.auth.signUp({
  email: 'user@example.com',
  password: 'password123'
})

// Sign in with email/password
const { data, error } = await supabase.auth.signInWithPassword({
  email: 'user@example.com',
  password: 'password123'
})

// Sign in with OAuth (Google, GitHub, etc.)
const { data, error } = await supabase.auth.signInWithOAuth({
  provider: 'google',
  options: {
    redirectTo: 'http://localhost:3000/auth/callback'
  }
})

// Sign out
await supabase.auth.signOut()

// Get current user
const { data: { user } } = await supabase.auth.getUser()

// Listen to auth changes
supabase.auth.onAuthStateChange((event, session) => {
  console.log(event, session)
})

Database Queries

// SELECT
const { data, error } = await supabase
  .from('posts')
  .select('*')

// SELECT with relations
const { data, error } = await supabase
  .from('posts')
  .select(`
    id,
    title,
    author:users(name, email)
  `)

// INSERT
const { data, error } = await supabase
  .from('posts')
  .insert({ title: 'Hello', content: 'World' })
  .select()

// UPDATE
const { data, error } = await supabase
  .from('posts')
  .update({ title: 'Updated' })
  .eq('id', 1)
  .select()

// DELETE
const { error } = await supabase
  .from('posts')
  .delete()
  .eq('id', 1)

// UPSERT
const { data, error } = await supabase
  .from('posts')
  .upsert({ id: 1, title: 'Upserted' })
  .select()

Query Filters

.eq('column', 'value')      // Equality
.neq('column', 'value')     // Not equal
.gt('column', 10)           // Greater than
.lt('column', 100)          // Less than
.gte('column', 10)          // Greater than or equal
.lte('column', 100)         // Less than or equal
.like('column', '%pattern%')      // Pattern matching
.ilike('column', '%pattern%')     // Case insensitive
.in('column', ['a', 'b', 'c'])    // IN array
.is('column', null)               // IS NULL
.order('created_at', { ascending: false })  // Ordering
.range(0, 9)                // Pagination (first 10)
.limit(10)                  // Limit results

Row Level Security (RLS)

-- Enable RLS on table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Allow users to read their own posts
CREATE POLICY "Users can read own posts"
ON posts FOR SELECT
USING (auth.uid() = user_id);

-- Allow users to insert their own posts
CREATE POLICY "Users can insert own posts"
ON posts FOR INSERT
WITH CHECK (auth.uid() = user_id);

-- Public read access
CREATE POLICY "Public read access"
ON posts FOR SELECT
TO anon
USING (true);

Storage

// Upload file
const { data, error } = await supabase.storage
  .from('avatars')
  .upload('user1/avatar.png', file)

// Get public URL
const { data } = supabase.storage
  .from('avatars')
  .getPublicUrl('user1/avatar.png')

// Create signed URL (temporary access)
const { data, error } = await supabase.storage
  .from('private-bucket')
  .createSignedUrl('path/to/file.pdf', 3600)

// Delete file
const { error } = await supabase.storage
  .from('avatars')
  .remove(['user1/avatar.png'])

Realtime Subscriptions

// Subscribe to database changes
const channel = supabase
  .channel('posts-changes')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'posts' },
    (payload) => {
      console.log('Change received!', payload)
    }
  )
  .subscribe()

// Unsubscribe
supabase.removeChannel(channel)

Environment Variables

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key  # Server-side only

CLI Commands

supabase init                    # Initialize project
supabase start                   # Start local development
supabase stop                    # Stop local development
supabase link --project-ref xxx  # Link to remote project
supabase db push                 # Push database migrations
supabase db pull                 # Pull remote schema
supabase migration new name      # Create new migration
supabase gen types typescript --local > types/supabase.ts  # Generate types
supabase functions deploy name   # Deploy Edge Functions

Key Concepts

  • Anon Key: Safe for client-side, respects RLS policies
  • Service Role Key: Bypasses RLS, server-side only, never expose to client
  • RLS: Enabled per-table, use auth.uid() to get current user's ID

Resources