| name | building-with-supabase |
| description | AI agent builds full-stack applications with Supabase PostgreSQL, authentication, Row Level Security, Edge Functions, and real-time subscriptions. Use when building apps with Supabase, implementing RLS policies, or setting up Supabase Auth. |
| category | databases |
| triggers | ["supabase","RLS","row level security","supabase auth","edge functions","real-time","supabase storage"] |
Building with Supabase
Purpose
Build secure, scalable applications using Supabase's PostgreSQL platform:
- Design tables with proper Row Level Security (RLS)
- Implement authentication flows (email, OAuth, magic link)
- Create real-time subscriptions for live updates
- Build Edge Functions for serverless logic
- Manage file storage with security policies
Quick Start
import { createClient } from '@supabase/supabase-js';
import { Database } from './types/supabase';
export const supabase = createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
import { createClient } from '@supabase/supabase-js';
export const supabaseAdmin = createClient<Database>(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
Features
| Feature | Description | Guide |
|---|
| PostgreSQL | Full Postgres with extensions (pgvector, PostGIS) | Direct SQL or Supabase client |
| Row Level Security | Per-row access control policies | Enable RLS + create policies |
| Authentication | Email, OAuth, magic link, phone OTP | Built-in auth.users table |
| Real-time | Live database change subscriptions | Channel subscriptions |
| Edge Functions | Deno serverless functions | TypeScript at edge |
| Storage | S3-compatible file storage | Buckets with RLS policies |
Common Patterns
RLS Policy Patterns
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can CRUD own posts" ON posts
FOR ALL
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Anyone can read posts" ON posts
FOR SELECT USING (published = true);
CREATE POLICY "Authenticated users can create" ON posts
FOR INSERT
WITH CHECK (auth.uid() IS NOT NULL);
CREATE POLICY "Team members can access" ON documents
FOR ALL
USING (
team_id IN (
SELECT team_id FROM team_members
WHERE user_id = auth.uid()
)
);
CREATE POLICY "Admins can do anything" ON users
FOR ALL
USING (auth.jwt() ->> 'role' = );
Authentication Flow
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'secure-password',
options: {
data: { full_name: 'John Doe' },
emailRedirectTo: 'https://app.com/auth/callback',
},
});
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'https://app.com/auth/callback',
scopes: 'email profile',
},
});
const { error } = await supabase.auth.signInWithOtp({
email: 'user@example.com',
options: { emailRedirectTo: 'https://app.com/auth/callback' },
});
const { data: { user } } = await supabase.auth.getUser();
await supabase.auth.signOut();
Real-time Subscriptions
const channel = supabase
.channel('posts-changes')
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'posts',
filter: 'user_id=eq.' + userId,
},
(payload) => {
console.log('Change:', payload.eventType, payload.new);
}
)
.subscribe();
channel.unsubscribe();
Edge Functions
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
serve(async (req) => {
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
const { record } = await req.json();
await supabase.from('processed').insert({ data: record });
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' },
});
});
Storage with Policies
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
CREATE POLICY "Users can upload own avatar" ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
CREATE POLICY "Anyone can view avatars" ON storage.objects
FOR SELECT USING (bucket_id = 'avatars');
const { data, error } = await supabase.storage
.from('avatars')
.upload(`${userId}/avatar.png`, file, {
cacheControl: '3600',
upsert: true,
});
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl(`${userId}/avatar.png`);
Next.js Server Components
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
export async function GET() {
const supabase = createRouteHandlerClient({ cookies });
const { data: posts } = await supabase.from('posts').select('*');
return Response.json(posts);
}
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
export default async function Page() {
const supabase = createServerComponentClient({ cookies });
const { data: posts } = await supabase.from('posts').select('*');
return <PostList posts={posts} />;
}
Use Cases
- Building SaaS applications with multi-tenant RLS
- Real-time collaborative applications
- Mobile app backends with authentication
- Serverless APIs with Edge Functions
- File upload systems with access control
Best Practices
| Do | Avoid |
|---|
| Enable RLS on all tables | Disabling RLS "temporarily" in production |
Use auth.uid() in policies, not session data | Trusting client-side user ID |
| Create service role client only server-side | Exposing service role key to client |
Use TypeScript types from supabase gen types | Manual type definitions |
| Filter subscriptions to reduce bandwidth | Subscribing to entire tables |
Use supabase db push for dev, migrations for prod | Pushing directly to production |
| Set up proper bucket policies | Public buckets for sensitive files |
Use signInWithOAuth for social auth | Custom OAuth implementations |
CLI Commands
supabase start
supabase db reset
supabase migration new add_posts
supabase db push
supabase db diff --use-migra
supabase gen types typescript --local > types/supabase.ts
supabase functions serve
supabase functions deploy my-func
Related Skills
See also these related skill documents:
- designing-database-schemas - Schema design patterns
- managing-database-migrations - Migration strategies
- implementing-oauth - OAuth flow details