.cursorrules (deprecated)
rules/supabase/.cursorrules.cursorrules
Quality
73/100
Scores the file, not the repository.Length
1,279 words
14 headings · 6 code blocksRepository
16
— · pushed 109 days agoLast changed
2 days ago
First indexed 2 days ago.1# Supabase Full-Stack Development — Cursor Rules23You are an expert full-stack developer building applications with Supabase as the backend, including database, auth, storage, edge functions, and real-time subscriptions.45## Code Style67- Use TypeScript throughout. Generate types from Supabase with `supabase gen types typescript`.8- Never use `any` when working with Supabase queries — use the generated `Database` type.9- Type your Supabase client: `const supabase = createClient<Database>(url, key)`.10- Use `camelCase` for application code, `snake_case` for database column and table names.11- Keep database queries in a data access layer (repository or service module), not in UI components.12- Use the Supabase client libraries, not raw HTTP calls to the REST API.1314## Database Design1516- Use PostgreSQL best practices. Supabase is PostgreSQL — leverage its full power.17- Use `uuid` primary keys generated with `gen_random_uuid()` for all tables.18- Include `created_at` (with default `now()`) and `updated_at` timestamps on every table.19- Use foreign key constraints for all relationships. Define `ON DELETE` behavior explicitly (CASCADE, SET NULL, RESTRICT).20- Use `text` over `varchar` in PostgreSQL (no performance difference, simpler). Add `CHECK` constraints for length limits.21- Use database enums for columns with fixed allowed values.22- Add indexes on columns used in WHERE, JOIN, and ORDER BY clauses.23- Use composite indexes for queries that filter on multiple columns.24- Name constraints and indexes explicitly: `idx_users_email`, `fk_posts_user_id`, `chk_users_email_format`.2526## Row-Level Security (RLS)2728- ALWAYS enable RLS on every table. No exceptions. Tables without RLS are publicly accessible.29- Write policies for every operation: SELECT, INSERT, UPDATE, DELETE. Be explicit about who can do what.30- Use `auth.uid()` to reference the current user in policies:31```sql32 CREATE POLICY "Users can read own data" ON users33 FOR SELECT USING (auth.uid() = id);34```35- Use `auth.jwt()` for claims-based access: `(auth.jwt() ->> 'role')::text = 'admin'`.36- Test RLS policies with different user roles. Use Supabase's policy testing tools.37- For public tables (e.g., published posts), create an explicit SELECT policy: `USING (published = true)`.38- Service role key bypasses RLS — never use it in client-side code.39- Use security definer functions for operations that need elevated privileges.4041## Authentication4243- Use Supabase Auth for all authentication. Do not build custom auth.44- Support multiple auth providers as needed: email/password, OAuth (Google, GitHub), magic link.45- Use `supabase.auth.getSession()` to check auth state. Use `supabase.auth.onAuthStateChange()` for reactive auth.46- Store user metadata in a separate `profiles` table linked to `auth.users` with a trigger:47```sql48 CREATE FUNCTION handle_new_user()49 RETURNS trigger AS $$50 BEGIN51 INSERT INTO public.profiles (id, email, full_name)52 VALUES (NEW.id, NEW.email, NEW.raw_user_meta_data ->> 'full_name');53 RETURN NEW;54 END;55 $$ LANGUAGE plpgsql SECURITY DEFINER;56```57- Implement proper sign-out: `await supabase.auth.signOut()`. Clear any local state.58- Use `supabase.auth.getUser()` for server-side verification (validates JWT with Supabase).59- Use `getSession()` for client-side checks only (session is from local storage, not verified).6061## Querying Data6263- Use the Supabase query builder for type-safe queries:64```typescript65 const { data, error } = await supabase66 .from('posts')67 .select('id, title, author:profiles(name, avatar_url)')68 .eq('published', true)69 .order('created_at', { ascending: false })70 .range(0, 9)71```72- Always handle errors: `if (error) { throw new Error(error.message) }`.73- Use `.select()` with specific columns instead of `*` to minimize data transfer.74- Use foreign table joins in `.select()` for related data: `'*, author:profiles(*)'`.75- Use `.range(from, to)` for pagination. Use `.limit()` for limiting results.76- Use `.single()` when expecting exactly one row (throws error if 0 or 2+ rows).77- Use `.maybeSingle()` when expecting 0 or 1 rows.78- Use RPC for complex queries: `supabase.rpc('function_name', { param: value })`.7980## Edge Functions8182- Write Edge Functions in TypeScript using Deno runtime.83- Use Edge Functions for: webhooks, third-party API integrations, complex server logic, scheduled tasks.84- Validate all input at the top of the function.85- Use the Supabase client with the service role key inside Edge Functions for admin operations.86- Set appropriate CORS headers for functions called from the browser.87- Handle errors and return consistent JSON responses with appropriate status codes.88- Use `Deno.env.get()` for accessing secrets and environment variables.89- Keep Edge Functions focused — one function per responsibility.9091## Real-Time9293- Use Supabase Realtime for live updates: database changes, presence, broadcast.94- Subscribe to database changes with channel subscriptions:95```typescript96 supabase.channel('posts')97 .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'posts' }, handleInsert)98 .subscribe()99```100- Use filters in subscriptions to limit the data received: `filter: 'user_id=eq.${userId}'`.101- Unsubscribe from channels when the component unmounts to prevent memory leaks.102- Use Presence for tracking online users: `channel.track({ user_id, online_at })`.103- Use Broadcast for ephemeral messages that don't need database persistence (typing indicators, cursor positions).104- Handle reconnection gracefully. Supabase client reconnects automatically, but re-subscribe to channels after reconnect.105106## Storage107108- Use Supabase Storage for file uploads (images, documents, media).109- Create storage buckets with appropriate policies:110```sql111 CREATE POLICY "Users can upload to own folder" ON storage.objects112 FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);113```114- Use signed URLs for private files. Use public URLs for publicly accessible assets.115- Validate file type and size on both client and server before upload.116- Organize files by user or entity: `avatars/{user_id}/photo.jpg`, `posts/{post_id}/cover.png`.117- Use image transformations for responsive images: `supabase.storage.from('bucket').getPublicUrl('path', { transform: { width: 200 } })`.118119## Migrations120121- Use Supabase CLI migrations for all schema changes: `supabase migration new migration_name`.122- Write both up and down migrations.123- Never modify a migration that has been applied to production. Create a new migration instead.124- Include RLS policies in migrations, not as ad-hoc SQL.125- Use seed files (`supabase/seed.sql`) for development test data.126- Test migrations locally with `supabase db reset` before deploying.127128## Testing129130- Use the local Supabase development environment (`supabase start`) for testing.131- Test RLS policies by creating test users and verifying access patterns.132- Test Edge Functions with `supabase functions serve` and HTTP client tests.133- Write integration tests that exercise the full stack: client -> RLS -> database.134- Use database transactions for test isolation when possible.135- Mock the Supabase client in unit tests for service logic.136137## File Structure138139```140src/141 lib/142 supabase/143 client.ts — Supabase client initialization144 types.ts — Generated Database types145 middleware.ts — Auth middleware / session handling146 services/147 auth.ts — Auth helper functions148 posts.ts — Post data access functions149 storage.ts — Storage upload/download helpers150 hooks/ — React/Svelte hooks for Supabase151 useAuth.ts152 usePosts.ts153 useRealtime.ts154supabase/155 config.toml — Supabase project configuration156 migrations/ — Database migrations157 001_create_profiles.sql158 002_create_posts.sql159 functions/ — Edge Functions160 send-email/161 index.ts162 process-webhook/163 index.ts164 seed.sql — Development seed data165```166167## Security168169- NEVER expose the service role key in client-side code. Use it only in server-side contexts (Edge Functions, server-side rendering).170- Use the `anon` key in client-side applications. It respects RLS policies.171- Enable RLS on ALL tables. Audit tables without RLS regularly.172- Validate and sanitize all user input before database operations.173- Use parameterized queries (Supabase client handles this). Never concatenate user input into SQL.174- Implement rate limiting on Edge Functions that are publicly accessible.175- Audit RLS policies when modifying table structures — new columns may need policy updates.176- Use `security definer` functions cautiously. They run with the function owner's permissions.177178## Performance179180- Use database indexes for frequently queried columns.181- Use `.select()` with specific columns to reduce payload size.182- Implement pagination for list endpoints — never return unbounded result sets.183- Use database functions (RPC) for complex aggregations instead of multiple client queries.184- Cache Supabase auth sessions client-side (the Supabase client does this automatically).185- Use connection pooling (Supabase uses PgBouncer). Prefer `transaction` mode for serverless.186- Optimize real-time subscriptions: subscribe only to the data you need, use filters.187
Also in survivorforge/cursor-rules
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/clean-code/.cursorrules · 16 | .cursorrules | styledo-notagent-behaviourdocs | 57/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 16 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-production/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+3 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/golang-api/.cursorrules · 16 | .cursorrules | buildteststylearch+6 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mcp-server/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+7 | 68/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 89/100 | 2 days ago |
Diff against rules/ai-ml-python/.cursorrules Diff against rules/api-design-rest/.cursorrules Diff against rules/api-microservices/.cursorrules Diff against rules/aws-serverless/.cursorrules Diff against rules/chrome-extension/.cursorrules Diff against rules/clean-code/.cursorrules Diff against rules/database-sql/.cursorrules Diff against rules/devops-docker/.cursorrules Diff against rules/devops-infrastructure/.cursorrules Diff against rules/django-rest/.cursorrules Diff against rules/docker-devops/.cursorrules Diff against rules/flutter-dart/.cursorrules Diff against rules/fullstack-nextjs-prisma/.cursorrules Diff against rules/go-gin/.cursorrules Diff against rules/go-production/.cursorrules Diff against rules/golang-api/.cursorrules Diff against rules/langchain-ai/.cursorrules Diff against rules/mcp-server/.cursorrules Diff against rules/mern-stack/.cursorrules Diff against rules/mobile-react-native/.cursorrules
