Overview
Supabase-specific patterns for building secure, real-time applications. Covers RLS policies, edge functions, real-time, storage, and auth.
Capabilities
- Implement Row Level Security (RLS) for multi-tenant data
- Write Supabase Edge Functions for serverless logic
- Set up real-time subscriptions for live data
- Integrate Supabase Auth with social providers
- Use Supabase Storage for file uploads
When to Use
Trigger phrases:
"supabase patterns"
"Supabase patterns — Row Level Security, edge functions, real-time subscriptions,"
Building multi-tenant SaaS with Supabase
Need real-time features (live updates, presence)
Serverless backend with Edge Functions
File storage and CDN for user uploads
When NOT to Use
- Task is about deployment, not development (use deploy skills)
- Task is about code review, not writing (use review skills)
- You need to understand existing code first (use research skills)
- Task is about testing only (use test skills)
- Requirements are unclear (clarify first)
- Task is trivially simple (single line fix)
Pseudo Code
The supabase-patterns workflow follows a standard pipeline pattern.
Core flow:
# supabase-patterns primary flow
input = prepare(raw_data)
result = process(input, config={auth, edge, functions, integration, level})
validate(result)
deliver(result)
Error handling:
on error:
log(error_details)
retry_with_backoff(max=3)
if still_failing: alert_and_escalate()
Row Level Security
-- Users can only see their own data
CREATE POLICY "users_own_data" ON orders
FOR ALL USING (auth.uid() = user_id);
-- Team members can see team data
CREATE POLICY "team_access" ON projects
FOR SELECT USING (
team_id IN (SELECT team_id FROM team_members WHERE user_id = auth.uid())
);
Edge Function
// supabase/functions/hello/index.ts
Deno.serve(async (req) => {
const { name } = await req.json()
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')!
)
const { data } = await supabase.from('greetings').insert({ name })
return new Response(JSON.stringify(data))
})
Real-time Subscription
const channel = supabase
.channel('orders')
.on('postgres_changes', { event: '*', schema: 'public', table: 'orders' }, handleUpdate)
.subscribe()
Common Patterns
- RLS always on: Enable RLS on every table — no exceptions
- Edge Functions for webhooks: Process Stripe, email events serverlessly
- Real-time for collaboration: Use presence and broadcast for multi-user features
Setup and Configuration
Project Setup
- Create a Supabase project — Start a new project in the Supabase dashboard, then copy the project URL and anon key.
- Install the SDK —
npm install @supabase/supabase-js
- Configure auth — Enable email/password, OAuth providers (Google, GitHub), or magic links in the Supabase dashboard.
- Define schema — Create tables, enable Row Level Security, write RLS policies, set up triggers.
- Build queries — Use the Supabase client for select, insert, update, delete with chained filters.
- Add real-time — Subscribe to table changes with Supabase Realtime channels.
Client Initialization
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);
Auth Example
const { data: { user } } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'password123',
});
Query with Joins
const { data: posts } = await supabase
.from('posts')
.select('*, author:profiles(*)')
.eq('status', 'published')
.order('created_at', { ascending: false });
How to Use
- Understand the requirement and existing codebase patterns
- Design the solution with error handling and testability in mind
- Implement incrementally with tests for each change
- Verify against expected outcomes (manual and automated)
- Document usage, edge cases, and integration points
- Review with team before merging to shared branches
Red Flags
- Skipping tests to ship faster: Untested code breaks in production when you least expect it
- No error handling in production code: Unhandled errors crash services and lose user data
- Hardcoded configuration values: Hardcoded values prevent environment switching and leak secrets
- Ignoring security implications: Missing input validation, auth bypasses, and injection vulnerabilities
- Over-engineering simple solutions: Premature abstraction adds complexity without proportional benefit
Verification
Process
- Analyze the task requirements
- Apply domain expertise
- Verify output quality
Anti-Rationalization Table
| Rationalization |
Reality |
| "Tests slow me down" |
Bugs slow you down 10x more. Tests are speed, not overhead. |
| "I will refactor later" |
Technical debt compounds. Refactor as you go. |
| "It works on my machine" |
If it is not in CI, it does not work. Ship proof, not claims. |
| "RLS is optional" |
Without RLS, any authenticated user can access any data. |
| "I will add auth later" |
Retrofitting auth is 10x harder than building with it from day one. |
1---2name: supabase-patterns3description: Use when supabase patterns — Row Level Security, edge functions, real-time subscriptions, auth integration, setup, and configuration. Use when working with supabase patterns.4license: Apache-2.05---6789## Overview1011Supabase-specific patterns for building secure, real-time applications. Covers RLS policies, edge functions, real-time, storage, and auth.1213## Capabilities1415- Implement Row Level Security (RLS) for multi-tenant data16- Write Supabase Edge Functions for serverless logic17- Set up real-time subscriptions for live data18- Integrate Supabase Auth with social providers19- Use Supabase Storage for file uploads2021## When to Use22**Trigger phrases:**23- "supabase patterns"24- "Supabase patterns — Row Level Security, edge functions, real-time subscriptions,"252627- Building multi-tenant SaaS with Supabase28- Need real-time features (live updates, presence)29- Serverless backend with Edge Functions30- File storage and CDN for user uploads3132## When NOT to Use3334- Task is about deployment, not development (use deploy skills)35- Task is about code review, not writing (use review skills)36- You need to understand existing code first (use research skills)37- Task is about testing only (use test skills)38- Requirements are unclear (clarify first)39- Task is trivially simple (single line fix)404142## Pseudo Code4344The supabase-patterns workflow follows a standard pipeline pattern.4546Core flow:47```48# supabase-patterns primary flow49input = prepare(raw_data)50result = process(input, config={auth, edge, functions, integration, level})51validate(result)52deliver(result)53```5455Error handling:56```57on error:58 log(error_details)59 retry_with_backoff(max=3)60 if still_failing: alert_and_escalate()61```626364### Row Level Security65```sql66-- Users can only see their own data67CREATE POLICY "users_own_data" ON orders68 FOR ALL USING (auth.uid() = user_id);6970-- Team members can see team data71CREATE POLICY "team_access" ON projects72 FOR SELECT USING (73 team_id IN (SELECT team_id FROM team_members WHERE user_id = auth.uid())74 );75```7677### Edge Function78```typescript79// supabase/functions/hello/index.ts80Deno.serve(async (req) => {81 const { name } = await req.json()82 const supabase = createClient(83 Deno.env.get('SUPABASE_URL')!,84 Deno.env.get('SUPABASE_ANON_KEY')!85 )86 const { data } = await supabase.from('greetings').insert({ name })87 return new Response(JSON.stringify(data))88})89```9091### Real-time Subscription92```typescript93const channel = supabase94 .channel('orders')95 .on('postgres_changes', { event: '*', schema: 'public', table: 'orders' }, handleUpdate)96 .subscribe()97```9899## Common Patterns100101- **RLS always on**: Enable RLS on every table — no exceptions102- **Edge Functions for webhooks**: Process Stripe, email events serverlessly103- **Real-time for collaboration**: Use presence and broadcast for multi-user features104105106## Setup and Configuration107108### Project Setup1091101. **Create a Supabase project** — Start a new project in the Supabase dashboard, then copy the project URL and anon key.1112. **Install the SDK** — `npm install @supabase/supabase-js`1123. **Configure auth** — Enable email/password, OAuth providers (Google, GitHub), or magic links in the Supabase dashboard.1134. **Define schema** — Create tables, enable Row Level Security, write RLS policies, set up triggers.1145. **Build queries** — Use the Supabase client for select, insert, update, delete with chained filters.1156. **Add real-time** — Subscribe to table changes with Supabase Realtime channels.116117### Client Initialization118119```typescript120import { createClient } from '@supabase/supabase-js';121122const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);123```124125### Auth Example126127```typescript128const { data: { user } } = await supabase.auth.signUp({129 email: 'user@example.com',130 password: 'password123',131});132```133134### Query with Joins135136```typescript137const { data: posts } = await supabase138 .from('posts')139 .select('*, author:profiles(*)')140 .eq('status', 'published')141 .order('created_at', { ascending: false });142```143144## How to Use1451461. Understand the requirement and existing codebase patterns1472. Design the solution with error handling and testability in mind1483. Implement incrementally with tests for each change1494. Verify against expected outcomes (manual and automated)1505. Document usage, edge cases, and integration points1516. Review with team before merging to shared branches152153## Red Flags154155- **Skipping tests to ship faster**: Untested code breaks in production when you least expect it156- **No error handling in production code**: Unhandled errors crash services and lose user data157- **Hardcoded configuration values**: Hardcoded values prevent environment switching and leak secrets158- **Ignoring security implications**: Missing input validation, auth bypasses, and injection vulnerabilities159- **Over-engineering simple solutions**: Premature abstraction adds complexity without proportional benefit160161## Verification162163- [ ] Skill output matches expected behavior164- [ ] Auth flow works (signup, login, logout)165- [ ] RLS policies enforce access control166- [ ] Queries return correct data167- [ ] Real-time subscriptions fire on changes168169## Process1701711. Analyze the task requirements1722. Apply domain expertise1733. Verify output quality174175## Anti-Rationalization Table176177| Rationalization | Reality |178|---|---|179| "Tests slow me down" | Bugs slow you down 10x more. Tests are speed, not overhead. |180| "I will refactor later" | Technical debt compounds. Refactor as you go. |181| "It works on my machine" | If it is not in CI, it does not work. Ship proof, not claims. |182| "RLS is optional" | Without RLS, any authenticated user can access any data. |183| "I will add auth later" | Retrofitting auth is 10x harder than building with it from day one. |