@tank/supabase-mastery
1.0.0Description
Production Supabase patterns covering RLS, auth, database functions and migrations, realtime, edge functions, storage, supabase-js v2, CLI workflows, Next.js integration, and self-hosting.
Triggered by
supabaseRLSauthrealtimeedge functionsstorage
Download
Review Recommended
tank install @tank/supabase-masterySupabase Mastery
Core Philosophy
- RLS is your authorization layer -- Row Level Security replaces application-level permission checks. Every table exposed to the API must have RLS enabled with policies, or data is either fully open (no RLS) or fully blocked (RLS on, no policies).
- Auth and database are one system -- Supabase Auth writes to
auth.usersin the same PostgreSQL instance. Useauth.uid()andauth.jwt()directly in RLS policies -- no separate authorization service needed. - Type safety from database to client -- Run
supabase gen types typescriptto generate types from your schema. Pass the generatedDatabasetype tocreateClient<Database>()for end-to-end type safety with zero manual type maintenance. - Server-side client for server code -- Use
createServerClient(from@supabase/ssr) in Next.js Server Components, Route Handlers, and Server Actions. UsecreateBrowserClientonly in Client Components. Never expose the service role key to the browser. - Wrap auth helper calls in
(select ...)for RLS performance --(select auth.uid()) = user_idcaches the function result per statement. Withoutselect, PostgreSQL callsauth.uid()per row, causing orders-of-magnitude slowdowns on large tables.
Quick-Start: Common Problems
"How do I set up auth with Next.js?"
- Install
@supabase/ssrand@supabase/supabase-js - Create server client utility using
createServerClientwith cookie handlers - Create browser client utility using
createBrowserClient - Add middleware to refresh sessions on every request
- Use server client in Server Components, browser client in Client Components
-> See
references/nextjs-integration.md
"My RLS policy blocks everything (or allows everything)"
- Verify RLS is enabled:
alter table <name> enable row level security - Check policy targets correct operation (SELECT/INSERT/UPDATE/DELETE)
- For SELECT, use
using (...). For INSERT, usewith check (...) - For UPDATE, supply both
using (...)andwith check (...) - Always specify the role with
to authenticatedorto anon - Test with
supabase.auth.getUser()-- notgetSession()-- for server-side validation -> Seereferences/rls-patterns.md
"Realtime subscriptions are not receiving events"
- Confirm RLS policies allow SELECT for the subscribing user
- Check that
supabase_realtimepublication includes the table - Verify the channel filter matches (schema, table, filter)
- For Postgres Changes, use
.on('postgres_changes', { event: '*', schema: 'public', table: 'messages' }, callback)-> Seereferences/realtime.md
"How do I structure a multi-tenant app?"
- Add
org_idcolumn to every tenant-scoped table - Store tenant membership in
app_metadatavia auth hooks or admin API - Write RLS policies using
auth.jwt()->'app_metadata'->>'org_id' - Use security definer functions for cross-tenant admin queries
-> See
references/rls-patterns.mdandreferences/auth-patterns.md
Decision Trees
Client Type Selection
| Context | Client | Package |
|---|---|---|
| Next.js Server Component / Route Handler | createServerClient | @supabase/ssr |
| Next.js Client Component | createBrowserClient | @supabase/ssr |
| Next.js Middleware | createServerClient (with cookie middleware) | @supabase/ssr |
| Edge Function | createClient with Authorization header | @supabase/supabase-js |
| React SPA (no SSR) | createClient | @supabase/supabase-js |
| Admin / service role | createClient with service role key | @supabase/supabase-js |
Auth Method Selection
| Requirement | Method |
|---|---|
| Standard email + password | signUp / signInWithPassword |
| Passwordless | Magic link (signInWithOtp) or OAuth |
| Social login (Google, GitHub, etc.) | signInWithOAuth with PKCE |
| Phone-based | signInWithOtp with phone |
| Enterprise SSO | SAML via Supabase SSO |
| Additional security factor | TOTP MFA enrollment + verification |
Data Access Method
| Need | Approach |
|---|---|
| CRUD from client with RLS | supabase-js query builder (.from().select()) |
| Complex query / aggregation | Database function + .rpc() |
| Webhook / external trigger | Edge Function |
| Scheduled job | Edge Function + pg_cron or external cron |
| File upload | Supabase Storage with RLS policies |
| Real-time updates | Realtime channel subscription |
Reference Index
| File | Contents |
|---|---|
references/rls-patterns.md | RLS policy syntax, CRUD policies, multi-tenant patterns, performance optimization, debugging, common mistakes |
references/auth-patterns.md | Email/OAuth/magic link/phone auth, MFA/TOTP, custom claims, auth hooks, session management, JWTs in Supabase |
references/database-patterns.md | PostgreSQL functions, triggers, views, generated columns, migrations, type generation, query patterns |
references/realtime.md | Postgres Changes, Broadcast, Presence, channel management, filtering, RLS interaction, performance |
references/edge-functions.md | Deno runtime, project structure, secrets, CORS, invoking from client, webhooks, testing, deployment |
references/storage.md | Bucket types, upload patterns, signed URLs, image transforms, storage RLS policies, CDN |
references/nextjs-integration.md | @supabase/ssr setup, server/browser clients, middleware, protected routes, Server Actions, cookie auth |
references/client-library.md | supabase-js v2 query builder, TypeScript generics, filtering, joins, pagination, error handling, realtime subscriptions |