| name | supabase-expert |
| description | Advanced Supabase integration specialist for Auth, Database (PostgreSQL/RLS), Storage, Realtime, Edge Functions, and AI/Vector features. Use when implementing Supabase features, debugging Supabase issues, setting up RLS policies, creating database schemas, building auth flows, optimizing Supabase queries, migrating to Supabase, or architecting Supabase-based applications. Invoke for Supabase client setup, type generation, migration creation, performance tuning, security audits, or Supabase best practices. Handles Next.js, React, Vue, Svelte, and server-side integrations. |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob |
| model | sonnet |
Supabase Expert Skill - Advanced Implementation Guide
Purpose
This is a comprehensive, production-grade skill for working with Supabase across all aspects of modern application development. It provides:
- Deep Technical Expertise: Advanced patterns for complex use cases
- Framework Integration: Specific implementations for Next.js, React, Vue, Svelte
- Production Readiness: Security audits, performance optimization, error handling
- Architecture Guidance: Multi-tenancy, scaling strategies, migration patterns
- Real-world Solutions: Battle-tested patterns from production applications
This skill leverages the complete Supabase documentation (2,190 pages) to provide accurate, up-to-date guidance across:
- Authentication & Authorization (30+ auth methods)
- PostgreSQL Database & RLS (Advanced query optimization)
- Storage & CDN (File management at scale)
- Realtime (WebSocket subscriptions, presence, broadcast)
- Edge Functions (Deno runtime, serverless patterns)
- AI/Vector (Embeddings, semantic search, RAG)
When to Use
Core Implementation Tasks
- Setting up Supabase client configuration and TypeScript types
- Implementing authentication (social login, magic links, SSO, MFA, anonymous auth)
- Creating PostgreSQL schemas with Row Level Security (RLS)
- Building realtime features with Supabase Realtime
- Implementing file storage with Supabase Storage
- Creating or debugging Edge Functions
- Working with vector embeddings and AI features
- Setting up local development with Supabase CLI
- Creating and managing database migrations
Advanced & Production Tasks
- Troubleshooting Supabase connection or query issues
- Optimizing Supabase queries and performance
- Implementing multi-tenancy with RLS
- Security audits and hardening
- Migration from Firebase, Parse, or other BaaS
- Architecting scalable Supabase applications
- Connection pooling and serverless optimization
- Implementing complex authorization patterns
- Setting up CI/CD with Supabase
- Monitoring and observability setup
Framework-Specific Integration
- Next.js App Router / Pages Router integration
- React with context and hooks
- Vue 3 with Composition API
- Svelte/SvelteKit integration
- Server-side rendering (SSR) with Supabase
- Static site generation (SSG) patterns
Documentation Access & Search Strategy
Documentation Location
Base Path: /Users/zach/Documents/cc-skills/docs/supabase/
Organized Structure
- guides/auth/ - Authentication (30+ files)
- guides/database/ - PostgreSQL, RLS, migrations, extensions (35+ files)
- guides/storage/ - File storage and CDN
- guides/realtime/ - Real-time subscriptions
- guides/functions/ - Edge Functions (35+ files)
- guides/ai/ - Vector embeddings and AI features (18+ files)
- guides/cli/ - Supabase CLI and local development
- guides/platform/ - Project management and deployment
- guides/security/ - Security best practices
- guides/deployment/ - Production deployment patterns
- reference/ - Complete API reference (1,583 files)
Advanced Search Strategy
When a request comes in, use a multi-stage search approach:
Stage 1: Broad Category Search
grep -r "keyword" /Users/zach/Documents/cc-skills/docs/supabase/guides/ -l | head -10
Stage 2: Targeted Deep Search
grep -r -B 2 -A 5 "specific pattern" /Users/zach/Documents/cc-skills/docs/supabase/guides/[category]/ --include="*.txt"
Stage 3: Cross-Reference Search
grep -r "related_term_1\|related_term_2\|related_term_3" /Users/zach/Documents/cc-skills/docs/supabase/ -l
Stage 4: API Reference Search
grep -r "method_name" /Users/zach/Documents/cc-skills/docs/supabase/reference/ -l
Documentation Reading Priority
- Guides - For conceptual understanding and best practices
- Reference - For specific API signatures and parameters
- Cross-reference - Check related topics for complete context
Enhanced Process Framework
1. Deep Requirement Analysis
Before providing any solution, analyze:
Technical Requirements:
- What Supabase feature is needed?
- What's the user's framework/environment?
- What's the scale/performance requirements?
- What are the security considerations?
Context Detection:
[ -f "next.config.js" ] && echo "Next.js detected"
[ -f "tsconfig.json" ] && echo "TypeScript project"
grep -r "createClient" . --include="*.{ts,js,tsx,jsx}" | head -5
Existing Code Analysis:
- Search for existing Supabase client setup
- Identify current patterns being used
- Check for potential conflicts or improvements
2. Comprehensive Documentation Search
Execute multi-stage search strategy:
AUTH_DOCS=$(grep -r "authentication\|sign.*in\|auth\..*" /Users/zach/Documents/cc-skills/docs/supabase/guides/auth/ -l)
OAUTH_DOCS=$(echo "$AUTH_DOCS" | xargs grep -l "google\|oauth")
3. Context-Aware Implementation
Provide implementations that match the user's context:
For Next.js App Router:
- Server Components patterns
- Server Actions integration
- Middleware for auth
- Cookie-based session management
For Next.js Pages Router:
- API routes patterns
- getServerSideProps integration
- Client-side auth hooks
For Client-Only React:
- Context providers
- Custom hooks
- Local state management
For Server-Side (Node/Deno/Bun):
- Service role patterns
- Connection pooling
- Background jobs
4. Production-Grade Implementation
Every code example should include:
✅ Complete TypeScript types
✅ Comprehensive error handling
✅ Loading states
✅ Edge cases handled
✅ Performance optimizations
✅ Security considerations
✅ Testing examples
✅ Monitoring/logging hooks
5. Validation & Testing Guidance
Provide:
- Unit test examples
- Integration test examples
- E2E test scenarios
- RLS policy testing
- Performance benchmarking
- Security audit checklist
Advanced Implementation Patterns
Pattern Library Location
.claude/skills/supabase-expert/patterns/
Pattern 1: Advanced RLS with Multi-Tenancy
Scenario: Multi-tenant SaaS with organization-based access control
Search Strategy:
grep -r "multi.*tenant\|organization\|team.*access" /Users/zach/Documents/cc-skills/docs/supabase/guides/ -l
grep -r "row.*level.*security.*tenant" /Users/zach/Documents/cc-skills/docs/supabase/guides/database/ --include="*.txt" -A 10
Implementation:
CREATE TABLE organizations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE organization_members (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'member')),
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(organization_id, user_id)
);
CREATE TABLE projects (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
created_by UUID REFERENCES auth.users(id),
created_at TIMESTAMPTZ DEFAULT NOW()
);
ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE organization_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
CREATE OR REPLACE is_organization_member(org_id UUID)
$$
(
organization_members
organization_id org_id
user_id auth.uid()
);
;
$$ plpgsql SECURITY DEFINER;
REPLACE get_user_role(org_id UUID)
TEXT $$
(
role organization_members
organization_id org_id
user_id auth.uid()
);
;
$$ plpgsql SECURITY DEFINER;
POLICY "Users can view their organizations"
organizations
(is_organization_member(id));
POLICY "Organization members can view projects"
projects
(is_organization_member(organization_id));
POLICY "Admins and owners can insert projects"
projects
(
get_user_role(organization_id) (, )
auth.uid() created_by
);
POLICY "Admins and owners can update projects"
projects
(get_user_role(organization_id) (, ));
POLICY "Owners can delete projects"
projects
(get_user_role(organization_id) );
INDEX idx_org_members_user organization_members(user_id);
INDEX idx_org_members_org organization_members(organization_id);
INDEX idx_projects_org projects(organization_id);
TypeScript Client Usage:
export interface Organization {
id: string
name: string
created_at: string
}
export interface OrganizationMember {
id: string
organization_id: string
user_id: string
role: 'owner' | 'admin' | 'member'
created_at: string
}
export interface Project {
id: string
organization_id: string
name: string
created_by: string
created_at: string
}
import { createClient } from '@supabase/supabase-js'
import type { Database } from '@/types/supabase'
export class OrganizationService {
constructor(private supabase: < createClient<>>) {}
() {
{ data, error } = .
.()
.()
(error) error
data
}
() {
{ data, error} = .
.()
.()
.(, organizationId)
.(, { : })
(error) error
data
}
() {
{ : { user } } = ...()
(!user) ()
{ data, error } = .
.()
.({
: organizationId,
name,
: user.
})
.()
.()
(error) error
data
}
}
Pattern 2: Advanced Auth with Custom Claims
Search Strategy:
grep -r "custom.*claims\|jwt.*metadata\|user.*metadata" /Users/zach/Documents/cc-skills/docs/supabase/guides/auth/ -l
grep -r "auth.*hooks\|hook.*send" /Users/zach/Documents/cc-skills/docs/supabase/guides/auth/ --include="*.txt" -A 10
Implementation:
import { createClient } from '@supabase/supabase-js'
export interface UserClaims {
role: 'admin' | 'user' | 'moderator'
organization_id?: string
permissions: string[]
}
export async function setUserClaims(
userId: string,
claims: UserClaims
): Promise<void> {
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
const { error } = await supabase.auth.admin.updateUserById(
userId,
{
app_metadata: { claims }
}
)
if (error) throw error
}
export async function getUserClaims(userId: string): Promise<UserClaims | null> {
supabase = (
process..!,
process..!
)
{ data, error } = supabase...(userId)
(error) error
data... ||
}
{ createServerClient }
{ , }
() {
response = .()
supabase = (
process..!,
process..!,
{
: {
() {
request..(name)?.
},
() {
response..({ name, value, ...options })
},
() {
response..({ name, : , ...options })
},
},
}
)
{ : { session } } = supabase..()
(request...()) {
(!session) {
.( (, request.))
}
claims = session...
(claims?. !== ) {
.( (, request.))
}
}
response
}
config = {
: [, ]
}
Pattern 3: Realtime with Presence and Broadcast
Search Strategy:
grep -r "presence\|broadcast\|realtime.*channel" /Users/zach/Documents/cc-skills/docs/supabase/guides/realtime/ -l
Implementation:
import { useEffect, useState } from 'react'
import { createClient } from '@supabase/supabase-js'
import type { RealtimeChannel } from '@supabase/supabase-js'
interface PresenceState {
[key: string]: {
user_id: string
username: string
online_at: string
}[]
}
export function usePresence(roomId: string) {
const [presenceState, setPresenceState] = useState<PresenceState>({})
const [channel, setChannel] = useState<RealtimeChannel | null>(null)
useEffect(() => {
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
const presenceChannel = supabase.channel(`room:${roomId}`, {
config: {
presence: {
key: 'user_id',
},
},
})
presenceChannel
.(, { : }, {
state = presenceChannel.()
(state)
})
.(, { : }, {
.(, key, newPresences)
})
.(, { : }, {
.(, key, leftPresences)
})
.( (status) => {
(status === ) {
{ : { user } } = supabase..()
(user) {
presenceChannel.({
: user.,
: user.,
: ().(),
})
}
}
})
(presenceChannel)
{
presenceChannel.()
}
}, [roomId])
= () => {
(channel) {
channel.({
: ,
event,
payload,
})
}
}
{
presenceState,
: .(presenceState).(),
sendBroadcast,
}
}
() {
{ onlineUsers, sendBroadcast } = (documentId)
= () => {
(, position)
}
(
)
}
Pattern 4: Vector Search with OpenAI Embeddings
Search Strategy:
grep -r "vector\|embedding\|pgvector\|similarity" /Users/zach/Documents/cc-skills/docs/supabase/guides/ai/ -l
grep -r "semantic.*search\|vector.*search" /Users/zach/Documents/cc-skills/docs/supabase/guides/ai/ --include="*.txt" -A 10
Implementation:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
content TEXT NOT NULL,
embedding vector(1536),
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
CREATE OR REPLACE FUNCTION match_documents(
query_embedding vector(1536),
match_threshold float,
match_count int
)
RETURNS TABLE (
id UUID,
content TEXT,
metadata JSONB,
similarity float
) LANGUAGE sql STABLE AS $$
SELECT
id,
content,
metadata,
1 - (embedding <=> query_embedding) AS similarity
FROM documents
WHERE 1 - (embedding <=> query_embedding) > match_threshold
ORDER BY embedding <=> query_embedding
LIMIT match_count;
$$;
TypeScript Implementation:
import { createClient } from '@supabase/supabase-js'
import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
export async function generateEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: 'text-embedding-ada-002',
input: text,
})
return response.data[0].embedding
}
export async function addDocument(
content: string,
metadata: Record<string, any> = {}
): Promise<void> {
embedding = (content)
{ error } = supabase
.()
.({
content,
embedding,
metadata,
})
(error) error
}
() {
queryEmbedding = (query)
{ data, error } = supabase.(, {
: queryEmbedding,
: matchThreshold,
: matchCount,
})
(error) error
data
}
(): <> {
relevantDocs = (userQuestion, , )
context = relevantDocs
.( doc.)
.()
response = openai...({
: ,
: [
{
: ,
: ,
},
{
: ,
: ,
},
],
})
response.[].. ||
}
Pattern 5: Edge Functions with Background Jobs
Search Strategy:
grep -r "edge.*function\|deno\|background.*job" /Users/zach/Documents/cc-skills/docs/supabase/guides/functions/ -l
Implementation:
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import Stripe from 'https://esm.sh/stripe@14.0.0'
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY') || '', {
apiVersion: '2023-10-16',
})
const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
)
interface PaymentRequest {
amount: number
currency: string
userId: string
organizationId: string
}
serve(async (req) => {
try {
const authHeader = req.headers.get('Authorization')
(!authHeader) {
(
.({ : }),
{ : }
)
}
{ : { user }, : authError } = supabase..(
authHeader.(, )
)
(authError || !user) {
(
.({ : }),
{ : }
)
}
: = req.()
paymentIntent = stripe..({
: body.,
: body.,
: {
: body.,
: body.,
},
})
{ : dbError } = supabase
.()
.({
: body.,
: body.,
: paymentIntent.,
: body.,
: body.,
: ,
})
(dbError) dbError
(
.({
: paymentIntent.,
: paymentIntent.,
}),
{
: { : },
: ,
}
)
} (error) {
(
.({ : error. }),
{
: { : },
: ,
}
)
}
})
Framework-Specific Implementations
Next.js App Router (Complete Setup)
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { cookies } from 'next/headers'
import type { Database } from '@/types/supabase'
export function createClient() {
const cookieStore = cookies()
return createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
},
set(name: string, value: string, options: CookieOptions) {
try {
cookieStore.set({ name, value, ...options })
} catch (error) {
}
},
remove(name: , : ) {
{
cookieStore.({ name, : , ...options })
} (error) {
}
},
},
}
)
}
{ createBrowserClient }
{ }
() {
createBrowserClient<>(
process..!,
process..!
)
}
{ createClient }
{ }
() {
{ searchParams, origin } = (request.)
code = searchParams.()
next = searchParams.() ??
(code) {
supabase = ()
{ error } = supabase..(code)
(!error) {
.()
}
}
.()
}
{ createClient }
{ redirect }
() {
supabase = ()
{
: { user },
} = supabase..()
(!user) {
()
}
{ : projects } = supabase
.()
.()
.(, { : })
(
)
}
{ createClient }
{ revalidatePath }
() {
supabase = ()
{
: { user },
} = supabase..()
(!user) {
{ : }
}
name = formData.()
organizationId = formData.()
{ data, error } = supabase
.()
.({
name,
: organizationId,
: user.,
})
.()
.()
(error) {
{ : error. }
}
()
{ data }
}
() {
supabase = ()
{ error } = supabase
.()
.()
.(, projectId)
(error) {
{ : error. }
}
()
{ : }
}
Performance Optimization Strategies
Strategy 1: Connection Pooling for Serverless
Search:
grep -r "connection.*pool\|supavisor\|serverless" /Users/zach/Documents/cc-skills/docs/supabase/guides/ -l
Implementation:
import { createClient } from '@supabase/supabase-js'
const POOLER_URL = process.env.SUPABASE_URL?.replace(
'.supabase.co',
'.pooler.supabase.com'
)
export function createPooledClient() {
return createClient(
POOLER_URL || process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!,
{
db: {
schema: 'public',
},
auth: {
persistSession: false,
},
}
)
}
export async function GET(request: Request) {
const supabase = createPooledClient()
const { data, error } = await supabase
.from('large_table')
.select('*')
.limit(1000)
return .({ data, error })
}
Strategy 2: Query Optimization
const { data } = await supabase
.from('users')
.select('*')
const { data } = await supabase
.from('users')
.select('id, email, username')
const { data, error, count } = await supabase
.from('users')
.select('*', { count: 'exact' })
.range(0, 49)
.order('created_at', { ascending: false })
const { data } = await supabase
.from('posts')
.select(`
id,
title,
author:users!inner(id, username),
comments(count)
`)
.eq('published', true)
.limit(10)
const { data } = await supabase
.from()
.()
.(, userId)
.(, )
Strategy 3: Caching Layer
import { createClient } from '@supabase/supabase-js'
import { unstable_cache } from 'next/cache'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!
)
export const getCachedProjects = unstable_cache(
async (organizationId: string) => {
const { data, error } = await supabase
.from('projects')
.select('*')
.eq('organization_id', organizationId)
.order('created_at', { ascending: false })
if (error) throw error
return data
},
['projects'],
{
revalidate: 60,
tags: ['projects'],
}
)
import { revalidateTag } from 'next/cache'
export async () {
{ data, error } = supabase
.()
.({ name, : orgId })
.()
.()
(!error) {
()
}
{ data, error }
}
Security Audit Checklist
Critical Security Checks
interface SecurityAudit {
checks: SecurityCheck[]
passed: boolean
failures: string[]
}
interface SecurityCheck {
name: string
passed: boolean
message?: string
}
export async function auditSupabaseSecurity(): Promise<SecurityAudit> {
const checks: SecurityCheck[] = []
const serviceKeyCheck = !process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY
checks.push({
name: 'Service Role Key Security',
passed: serviceKeyCheck,
message: serviceKeyCheck
? 'Service role key not exposed in public env vars'
: '❌ CRITICAL: Service role key exposed in public env vars!',
})
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
const { : tables } = supabase.()
rlsCheck = tables?.( t.)
checks.({
: ,
: rlsCheck || ,
: rlsCheck
?
: ,
})
sqlInjectionCheck =
checks.({
: ,
: sqlInjectionCheck,
})
httpsCheck = process..?.()
checks.({
: ,
: httpsCheck || ,
: httpsCheck ? : ,
})
passed = checks.( check.)
failures = checks
.( !check.)
.( check. || check.)
{ checks, passed, failures }
}
Testing Utilities
RLS Policy Testing
import { createClient } from '@supabase/supabase-js'
import { describe, it, expect, beforeAll } from 'vitest'
describe('RLS Policies', () => {
let supabase: ReturnType<typeof createClient>
let testUserId: string
beforeAll(async () => {
supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
const { data: { user } } = await supabase.auth.admin.createUser({
email: 'test@example.com',
password: 'test-password-123',
email_confirm: true,
})
testUserId = user!.id
})
it('should allow users to read their own data', async () => {
const { data: { session } } = await supabase.auth.signInWithPassword({
email: ,
: ,
})
userClient = (
process..!,
process..!,
{
: {
: {
: ,
},
},
}
)
{ data, error } = userClient
.()
.()
.(, testUserId)
(error).()
(data).()
})
(, () => {
{ : { session } } = supabase..({
: ,
: ,
})
userClient = (
process..!,
process..!,
{
: {
: {
: ,
},
},
}
)
{ data, error } = userClient
.()
.()
.(, testUserId)
(data).()
})
})
Error Handling Framework
Comprehensive Error Handler
import { PostgrestError } from '@supabase/supabase-js'
export class SupabaseError extends Error {
constructor(
public code: string,
public details: string,
public hint?: string
) {
super(details)
this.name = 'SupabaseError'
}
}
export function handleSupabaseError(error: PostgrestError | null): never {
if (!error) {
throw new Error('Unknown error occurred')
}
if (error.code === '42501' || error.message.includes('policy')) {
throw new SupabaseError(
'RLS_POLICY_VIOLATION',
'You do not have permission to perform this action',
'Check row-level security policies'
)
}
(error. === ) {
field = error..()?.[]
(
,
,
)
}
(error. === ) {
(
,
,
)
}
(error..()) {
(
,
,
)
}
(
error. || ,
error.,
error.
)
}
{
{ data, error } = supabase
.()
.({ : })
(error) (error)
data
} (err) {
(err ) {
.()
(err.) .()
{
: ,
: err.,
: err.,
}
}
err
}
Monitoring & Observability
import { createClient } from '@supabase/supabase-js'
interface QueryLog {
query: string
duration: number
error?: string
timestamp: string
}
export class SupabaseMonitor {
private logs: QueryLog[] = []
constructor(private supabase: ReturnType<typeof createClient>) {
this.wrapClient()
}
private wrapClient() {
const originalFrom = this.supabase.from.bind(this.supabase)
this.supabase.from = (table: string) => {
const startTime = Date.now()
const builder = originalFrom(table)
const wrapMethod = () => {
original = (builder )[method].(builder)
;(builder )[method] = (...: []) => {
result = (...args)
duration = .() - startTime
..({
: ,
duration,
: result.?.,
: ().(),
})
(duration > ) {
.()
}
result
}
}
;[, , , , ].(wrapMethod)
builder
}
}
() {
.
}
() {
..( log. > threshold)
}
() {
totalQueries = ..
errorQueries = ..( log.).
totalQueries > ? errorQueries / totalQueries :
}
}
Migration Utilities
Migration from Firebase
import admin from 'firebase-admin'
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
admin.initializeApp({
credential: admin.credential.cert('./firebase-credentials.json'),
})
export async function migrateUsers() {
const auth = admin.auth()
let nextPageToken: string | undefined
do {
const listUsersResult = await auth.listUsers(1000, nextPageToken)
for (const userRecord of listUsersResult.users) {
try {
const { data, error } = await supabase.auth.admin.createUser({
email: userRecord.email!,
email_confirm: true,
: {
: userRecord.,
: userRecord.,
: ,
},
})
(error) {
.(, error)
}
.()
} (err) {
.(, err)
}
}
nextPageToken = listUsersResult.
} (nextPageToken)
}
() {
firestore = admin.()
snapshot = firestore.(collectionName).()
( doc snapshot.) {
data = doc.()
row = {
: doc.,
...data,
: data.?.
? (data.. * ).()
: ,
}
{ error } = supabase
.(tableName)
.(row)
(error) {
.(, error)
} {
.()
}
}
}
Output Format
When providing Supabase guidance, follow this comprehensive format:
1. Deep Analysis
- Understand user's context (framework, scale, requirements)
- Identify potential challenges and edge cases
- Consider security implications
2. Documentation Research
- Cite specific documentation files consulted
- Reference API documentation for exact signatures
- Cross-reference related features
3. Production-Grade Implementation
- Complete TypeScript code with all types
- Comprehensive error handling
- Loading states and edge cases
- Performance optimizations built-in
- Security best practices applied
- Monitoring/logging hooks
4. Testing Strategy
- Unit test examples
- Integration test scenarios
- RLS policy testing
- E2E test guidance
5. Deployment Guidance
- Environment variable setup
- Migration scripts
- Rollback procedures
- Monitoring setup
6. Performance Considerations
- Query optimization tips
- Caching strategies
- Connection pooling guidance
- Index recommendations
7. Security Review
- RLS policy review
- Input validation
- API key security
- CORS configuration
8. Next Steps & Scaling
- Related features to implement
- Scaling considerations
- Advanced patterns to explore
Notes
- Always search documentation first - Consult 2,190 pages before answering
- PostgreSQL expertise required - Supabase is PostgreSQL, apply PG best practices
- Deno for Edge Functions - Not Node.js, different module system
- RLS is mandatory - Test thoroughly, security is critical
- Type generation is essential - Always generate types from schema
- Connection pooling - Required for serverless/Edge deployments
- Service role = superuser - Never expose to clients
- Anon key is safe - Can be used in client-side code
- Local development - Requires Docker for Supabase CLI
- Test RLS exhaustively - Use multiple user contexts
Documentation Search Shortcuts
alias sb-auth="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/auth/ -l"
alias sb-db="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/database/ -l"
alias sb-storage="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/storage/ -l"
alias sb-realtime="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/realtime/ -l"
alias sb-functions="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/functions/ -l"
alias sb-ai="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/guides/ai/ -l"
alias sb-api="grep -r '$1' /Users/zach/Documents/cc-skills/docs/supabase/reference/ -l | head -20"
Quick Reference Commands
supabase init
supabase start
supabase status
supabase stop
supabase migration new <name>
supabase db reset
supabase db push
supabase db pull
supabase db diff
supabase gen types typescript --local
supabase gen types typescript --project-id <id>
supabase functions new <name>
supabase functions serve
supabase functions deploy <name>
supabase functions logs <name>
supabase auth users list
supabase auth users get <user-id>
supabase secrets set SECRET_NAME=value
supabase secrets list