--- description: "Supabase conventions for {{PROJECT_NAME}}" alwaysApply: true --- # Supabase Standards — {{PROJECT_NAME}} ## Row Level Security (RLS) awareness - **ALWAYS** assume RLS is enabled — never write queries that assume full table access - Test queries in the Supabase dashboard before implementing in Flutter - If a query returns empty unexpectedly, check RLS policies first ## Queries ```dart // ✅ Type-safe query with error handling Future> getProducts() async { final response = await _supabase .from('products') .select('id, name, price, category_id, categories(name)') .eq('is_active', true) .order('created_at', ascending: false) .limit(50); return response.map(Product.fromMap).toList(); } ``` ## Realtime subscriptions ```dart StreamSubscription>>? _sub; void watchOrders(String userId) { _sub = _supabase .from('orders') .stream(primaryKey: ['id']) .eq('user_id', userId) .listen( (data) => _updateOrders(data), onError: (e) => _handleError(e), ); } @override void dispose() { _sub?.cancel(); // ALWAYS cancel in dispose() super.dispose(); } ``` ## Auth session - Use `supabase.auth.onAuthStateChange` stream — never poll auth state - Persist session: `supabase-flutter` handles this automatically via secure storage - `session.accessToken` expires — check `session.isExpired` before sensitive operations