| name | supabase-dev-guidelines |
| description | Auth (Google/Facebook OAuth, email), Database (PostgreSQL, RLS policies, SECURITY DEFINER), Edge Functions, Realtime subscriptions. Uzywaj przy pracy z autentykacja, baza danych, migracjami, bezpieczenstwem. |
| paths | ["supabase/**","**/*.sql","src/lib/**","src/hooks/**"] |
Supabase Development Guidelines
Cel
Kompleksowy przewodnik dla pracy z Supabase w aplikacjach Vite SPA - autentykacja, baza danych, RLS policies, Edge Functions i bezpieczeństwo.
Kiedy Używać Tego Skilla
- Praca z autentykacją (login, rejestracja, OAuth)
- Tworzenie lub modyfikacja tabel bazy danych
- Pisanie RLS policies
- Tworzenie Edge Functions
- Migracje bazy danych
- Bezpieczeństwo i audit logging
Quick Start
Checklist Nowej Tabeli
Checklist Edge Function
Checklist Bezpieczeństwa
Klient Supabase
Typed Client (Standard 2026)
import { createClient } from '@supabase/supabase-js';
import type { Database } from '@/types/database';
export const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
);
export type Tables<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Row'];
export type InsertTables<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Insert'];
export type UpdateTables<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Update'];
Generowanie Typów
supabase gen types typescript --local > src/types/database.ts
supabase gen types typescript --project-id YOUR_PROJECT_ID > src/types/database.ts
Podstawowe Operacje
const { data, error } = await supabase
.from('posts')
.select('*')
.eq('published', true)
.order('created_at', { ascending: false });
const { data, error } = await supabase
.from('posts')
.insert({ title, content, user_id: userId });
const { data, error } = await supabase
.from('profiles')
.update({ display_name: newName })
.eq('id', userId);
const { data, error } = await supabase
.from('bookmarks')
.delete()
.eq('user_id', userId)
.eq('post_id', postId);
const { data, error } = await supabase.rpc('ensure_user_profile');
Topic Guides
Autentykacja
Dostępne metody:
- OAuth (Google, Facebook, GitHub, Discord, etc.)
- Email/hasło
Kluczowe Koncepcje:
- PKCE z auto-detekcją (
detectSessionInUrl: true — domyślnie); nie wymieniaj code ręcznie w przeglądarce
- Hook
useAuth() zarządza sesją
- Trigger
handle_new_user() tworzy rekord w public.profiles
- Funkcja
ensure_user_profile() jako fallback
getSession() dla UI, getUser() lub getClaims() dla krytycznych operacji
Pełny Przewodnik: resources/auth-patterns.md
Baza Danych i RLS
Wzorcowe Tabele:
profiles - dane użytkowników (1:1 z auth.users)
posts - treści z własnością użytkownika
comments - relacje do postów i użytkowników
bookmarks - relacja many-to-many
audit_log - logowanie krytycznych operacji (write-only)
RLS Patterns:
- Public read:
USING (true)
- Own data:
USING ((SELECT auth.uid()) = user_id)
- Conditional:
USING (published = true OR (SELECT auth.uid()) = user_id)
- Service only: brak policies (tylko service_role)
Pełny Przewodnik: resources/database-patterns.md
Edge Functions
Typowe Zastosowania:
- Stripe Checkout / Webhooks
- Integracje z zewnętrznymi API
- Operacje wymagające service_role
Wzorce 2026:
Deno.serve() (wbudowane, bez importu)
jsr:@supabase/supabase-js@2 (nie esm.sh)
npm:stripe@22 (nie esm.sh)
constructEventAsync dla Stripe webhooks
- Runtime: Deno 2.x (upgrade z 1.45.2)
deno.json preferowany nad import maps
Pełny Przewodnik: resources/edge-functions.md
Bezpieczeństwo
Kluczowe Wzorce:
- RLS dla izolacji danych
- UUID w policies (nie email - email jest mutowalny)
- SECURITY DEFINER dla uprawnionych operacji
- Audit log izolowany (bez INSERT dla authenticated)
- Logowanie przez triggers lub SECURITY DEFINER functions
Pełny Przewodnik: resources/security.md
Realtime (Opcjonalnie)
Użycie:
- Subscriptions dla zmian w tabelach
- Presence dla statusu użytkowników
- Broadcast dla custom events
Pełny Przewodnik: resources/realtime.md
Navigation Guide
Główne Zasady
- RLS Zawsze Włączony: Każda tabela musi mieć RLS
- UUID w Policies:
auth.uid() = user_id, nigdy email
- Generated Types:
supabase gen types po każdej migracji
- SECURITY DEFINER Ostrożnie: Zawsze
SET search_path = '' (pusty) + w pełni kwalifikowane nazwy (public.tabela)
- Service Role Tylko w Edge Functions: Nigdy nie eksponuj na froncie
- Audit Log Izolowany: Wpisy tylko przez triggers/SECURITY DEFINER
- Logger dla Błędów:
logger.error() zamiast console.error()
Zmienne Środowiskowe
Frontend (.env.local)
VITE_SUPABASE_URL=your_supabase_url
VITE_SUPABASE_ANON_KEY=your_anon_key
Edge Functions
SUPABASE_URL=...
SUPABASE_SERVICE_ROLE_KEY=... # NIGDY nie commituj!
STRIPE_SECRET_KEY=... # NIGDY nie commituj!
STRIPE_WEBHOOK_SECRET=... # NIGDY nie commituj!
Częste Błędy
Unikaj
const supabase = createClient(url, SERVICE_ROLE_KEY);
USING (user_email = auth.email())
const { data } = await supabase.from('posts').select('*');
console.error('DB error:', error);
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
const { data: { session } } = await supabase.auth.getSession();
if (session) { }
Preferuj
const supabase = createClient(url, ANON_KEY);
USING (auth.uid() = user_id)
const { data } = await supabase.from('posts').select('*');
logger.error('Błąd operacji', error);
Deno.serve(async (req) => { ... });
const { data: { user } } = await supabase.auth.getUser();
if (user) { }
Status Skilla: Modułowa struktura z progressive loading dla optymalnego zarządzania kontekstem. Zaktualizowany do standardów Marzec 2026.