Supabase Integration Expert
Purpose
Provide comprehensive, accurate guidance for building applications with Supabase based on 2,616+ official documentation files. Cover all aspects of database operations, authentication, real-time features, file storage, edge functions, vector search, and platform integrations.
Documentation Coverage
Full access to official Supabase documentation (when available):
- Location:
docs/supabase_com/ - Files: 2,616 markdown files
- Coverage: Complete guides, API references, client libraries, and platform docs
Note: Documentation must be pulled separately:
bash
pipx install docpull
docpull https://supabase.com/docs -o .claude/skills/supabase/docs
Major Areas:
- Database: PostgreSQL, Row Level Security (RLS), migrations, functions, triggers
- Authentication: Email/password, OAuth, magic links, SSO, MFA, phone auth
- Real-time: Database changes, broadcast, presence, channels
- Storage: File uploads, image transformations, CDN, buckets
- Edge Functions: Deno runtime, serverless, global deployment
- Vector/AI: pgvector, embeddings, semantic search, RAG
- Client Libraries: JavaScript, Python, Dart (Flutter), Swift, Kotlin
- Platform: CLI, local development, branching, observability
- Integrations: Next.js, React, Vue, Svelte, React Native, Expo
When to Use
Invoke when user mentions:
- Database: PostgreSQL, Postgres, SQL, database, tables, queries, migrations
- Auth: authentication, login, signup, OAuth, SSO, multi-factor, magic links
- Real-time: real-time, subscriptions, websocket, live data, presence, broadcast
- Storage: file upload, file storage, images, S3, CDN, buckets
- Functions: edge functions, serverless, API, Deno, cloud functions
- Security: Row Level Security, RLS, policies, permissions, access control
- AI/ML: vector search, embeddings, pgvector, semantic search, AI, RAG
- Framework Integration: Next.js, React, Supabase client, hooks
How to Use Documentation
When answering questions:
- Search for specific topics:
``bash # Use Grep to find relevant docs grep -r "row level security" docs/supabase_com/ --include="*.md" ``
- Find guides:
``bash # Guides are organized by feature ls docs/supabase_com/guides_* ``
- Check reference docs:
``bash # Reference docs for client libraries ls docs/supabase_com/reference_* ``
Quick Start
Installation
bash
npm install @supabase/supabase-js
Initialize Client
typescript
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
Environment Variables:
NEXT_PUBLIC_SUPABASE_URL - Your project URL (safe for client)NEXT_PUBLIC_SUPABASE_ANON_KEY - Anonymous/public key (safe for client)SUPABASE_SERVICE_ROLE_KEY - Admin key (server-side only, bypasses RLS)
Database Operations
CRUD Operations
typescript
// Insert
const { data, error } = await supabase
.from('posts')
.insert({
title: 'Hello World',
content: 'My first post',
user_id: user.id,
})
.select()
.single();
// Read (with filters)
const { data: posts } = await supabase
.from('posts')
.select('*')
.eq('published', true)
.order('created_at', { ascending: false })
.limit(10);
// Update
const { data, error } = await supabase
.from('posts')
.update({ published: true })
.eq('id', postId)
.select()
.single();
// Delete
const { error } = await supabase
.from('posts')
.delete()
.eq('id', postId);
// Upsert (insert or update)
const { data, error } = await supabase
.from('profiles')
.upsert({
id: user.id,
name: 'John Doe',
updated_at: new Date().toISOString(),
})
.select();
Advanced Queries
typescript
// Joins
const { data } = await supabase
.from('posts')
.select(`
*,
author:profiles(name, avatar),
comments(count)
`)
.eq('published', true);
// Full-text search
const { data } = await supabase
.from('posts')
.select('*')
.textSearch('title', `'nextjs' & 'supabase'`);
// Range queries
const { data } = await supabase
.from('posts')
.select('*')
.gte('created_at', '2024-01-01')
.lt('created_at', '2024-12-31');
// JSON queries
const { data } = await supabase
.from('posts')
.select('*')
.contains('metadata', { tags: ['tutorial'] });
Database Functions
typescript
// Call stored procedure
const { data, error } = await supabase
.rpc('get_user_stats', {
user_id: userId,
});
// Call with filters
const { data } = await supabase
.rpc('search_posts', { search_term: 'supabase' })
.limit(10);
Authentication
Sign Up / Sign In
typescript
// Email/password signup
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'secure-password',
options: {
data: {
first_name: 'John',
last_name: 'Doe',
},
},
});
// Email/password sign in
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'secure-password',
});
// Magic link (passwordless)
const { data, error } = await supabase.auth.signInWithOtp({
email: 'user@example.com',
options: {
emailRedirectTo: 'https://example.com/auth/callback',
},
});
// Phone/SMS
const { data, error } = await supabase.auth.signInWithOtp({
phone: '+1234567890',
});
OAuth Providers
typescript
// Google sign in
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'http://localhost:3000/auth/callback',
scopes: 'profile email',
},
});
Supported providers:
- Google, GitHub, GitLab, Bitbucket
- Azure, Apple, Discord, Facebook
- Slack, Spotify, Twitch, Twitter/X
- Linear, Notion, Figma, and more
User Session Management
typescript
// Get current user
const { data: { user } } = await supabase.auth.getUser();
// Get session
const { data: { session } } = await supabase.auth.getSession();
// Sign out
const { error } = await supabase.auth.signOut();
// Listen to auth changes
supabase.auth.onAuthStateChange((event, session) => {
if (event === 'SIGNED_IN') {
console.log('User signed in:', session.user);
}
if (event === 'SIGNED_OUT') {
console.log('User signed out');
}
if (event === 'TOKEN_REFRESHED') {
console.log('Token refreshed');
}
});
Multi-Factor Authentication (MFA)
typescript
// Enroll MFA
const { data, error } = await supabase.auth.mfa.enroll({
factorType: 'totp',
friendlyName: 'My Authenticator App',
});
// Verify MFA
const { data, error } = await supabase.auth.mfa.challengeAndVerify({
factorId: data.id,
code: '123456',
});
// List factors
const { data: factors } = await supabase.auth.mfa.listFactors();
Row Level Security (RLS)
Enable RLS
sql
-- Enable RLS on table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
Create Policies
sql
-- Public read access
CREATE POLICY "Posts are viewable by everyone"
ON posts FOR SELECT
USING (true);
-- Users can insert their own posts
CREATE POLICY "Users can create posts"
ON posts FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Users can update only their posts
CREATE POLICY "Users can update own posts"
ON posts FOR UPDATE
USING (auth.uid() = user_id);
-- Users can delete only their posts
CREATE POLICY "Users can delete own posts"
ON posts FOR DELETE
USING (auth.uid() = user_id);
-- Conditional access (e.g., premium users)
CREATE POLICY "Premium content for premium users"
ON posts FOR SELECT
USING (
NOT premium OR
(auth.uid() IN (
SELECT user_id FROM subscriptions
WHERE status = 'active'
))
);
Helper Functions
sql
-- Get current user ID
auth.uid()
-- Get current JWT
auth.jwt()
-- Access JWT claims
(auth.jwt()->>'role')::text
(auth.jwt()->>'email')::text
Real-time Subscriptions
Listen to Database Changes
typescript
const channel = supabase
.channel('posts-changes')
.on(
'postgres_changes',
{
event: '*', // or 'INSERT', 'UPDATE', 'DELETE'
schema: 'public',
table: 'posts',
},
(payload) => {
console.log('Change received:', payload);
}
)
.subscribe();
// Cleanup
channel.unsubscribe();
Filter Real-time Events
typescript
// Only listen to specific user's posts
const channel = supabase
.channel('my-posts')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'posts',
filter: `user_id=eq.${userId}`,
},
(payload) => {
console.log('New post:', payload.new);
}
)
.subscribe();
Broadcast (Ephemeral Messages)
typescript
const channel = supabase.channel('chat-room');
// Send message
await channel.send({
type: 'broadcast',
event: 'message',
payload: { text: 'Hello!', user: 'John' },
});
// Receive messages
channel.on('broadcast', { event: 'message' }, (payload) => {
console.log('Message:', payload.payload);
});
await channel.subscribe();
Presence Tracking
typescript
const channel = supabase.channel('room-1');
// Track presence
channel
.on('presence', { event: 'sync' }, () => {
const state = channel.presenceState();
console.log('Online users:', Object.keys(state).length);
})
.on('presence', { event: 'join' }, ({ key, newPresences }) => {
console.log('User joined:', newPresences);
})
.on('presence', { event: 'leave' }, ({ key, leftPresences }) => {
console.log('User left:', leftPresences);
})
.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await channel.track({
user_id: userId,
online_at: new Date().toISOString(),
});
}
});
Storage
Upload Files
typescript
const file = event.target.files[0];
const { data, error } = await supabase.storage
.from('avatars')
.upload(`public/${userId}/avatar.png`, file, {
cacheControl: '3600',
upsert: true,
});
// Upload from base64
const { data, error } = await supabase.storage
.from('avatars')
.upload('file.png', decode(base64String), {
contentType: 'image/png',
});
Download Files
typescript
// Download as blob
const { data, error } = await supabase.storage
.from('avatars')
.download('public/avatar.png');
const url = URL.createObjectURL(data);
Public URLs
typescript
// Get public URL (for public buckets)
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('public/avatar.png');
console.log(data.publicUrl);
Signed URLs (Private Files)
typescript
// Create temporary access URL
const { data, error } = await supabase.storage
.from('private-files')
.createSignedUrl('document.pdf', 3600); // 1 hour
console.log(data.signedUrl);
Image Transformations
typescript
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('avatar.png', {
transform: {
width: 400,
height: 400,
resize: 'cover', // 'contain', 'cover', 'fill'
quality: 80,
},
});
List Files
typescript
const { data, error } = await supabase.storage
.from('avatars')
.list('public', {
limit: 100,
offset: 0,
sortBy: { column: 'created_at', order: 'desc' },
});
Edge Functions
Create Function
bash
# Install Supabase CLI
npm install -g supabase
# Initialize project
supabase init
# Create function
supabase functions new my-function
Function Example
typescript
// supabase/functions/my-function/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';