Supabase Integration
Overview
GigPilot AI uses Supabase for authentication, database, and storage services.
Configuration
| Variable | Description |
|---|---|
SUPABASE_URL |
Your Supabase project URL |
SUPABASE_ANON_KEY |
Public anonymous key (client-side) |
SUPABASE_SERVICE_ROLE_KEY |
Admin key (server-side, bypasses RLS) |
Client Types
Admin Client (Server)
Used for background jobs and operations that bypass Row Level Security.
import { supabaseAdmin } from '../lib/supabase';
// Bypasses RLS - use for admin operationsconst { data, error } = await supabaseAdmin .from('profiles') .select('*');File: apps/backend/src/lib/supabase.ts
User-Scoped Client (Server)
Created per-request with the user’s JWT token to respect RLS policies.
import { getSupabaseUserClient } from '../lib/supabase';
// Respects RLS - use for user operationsconst client = getSupabaseUserClient(userToken);const { data, error } = await client .from('profiles') .select('*') .eq('id', userId);Frontend Client
Created in the browser for auth and direct Supabase operations.
import { createClient } from '@supabase/supabase-js';
const supabase = createClient( import.meta.env.PUBLIC_SUPABASE_URL, import.meta.env.PUBLIC_SUPABASE_ANON_KEY);File: apps/frontend/src/lib/api-client.ts
Authentication
Google OAuth
Configured through Supabase Auth dashboard.
Flow:
- Frontend calls
supabase.auth.signInWithOAuth({ provider: 'google' }) - User authenticates with Google
- Supabase handles callback and creates session
- Frontend exchanges session with backend
/api/auth/login
Callback Handler: apps/frontend/src/pages/auth/callback.astro
Magic Link
Supabase-powered passwordless login.
const { data, error } = await supabase.auth.signInWithOtp({ email: 'user@example.com'});Session Management
// Get current sessionconst { data: { session } } = await supabase.auth.getSession();
// Get current userconst { data: { user } } = await supabase.auth.getUser();
// Sign outawait supabase.auth.signOut();Row Level Security (RLS)
When using user-scoped clients, RLS policies control data access. The backend creates per-request Supabase clients with the user’s JWT token.
Default Policies:
- Users can only read/write their own data
user_idcolumn matches the authenticated user’s ID- Admin client bypasses all RLS policies
Storage
Bucket: gigpilot-assets
Used for file uploads (images, PDFs).
Configuration:
| Setting | Value |
|---|---|
| Bucket Name | gigpilot-assets |
| Public | No (signed URLs) |
| File Size Limit | 5 MB |
| Allowed Types | JPEG, PNG, WEBP, GIF, PDF |
Upload Flow:
- Client sends base64-encoded file to
/api/storage/upload - Backend decodes to buffer
- Uploads to Supabase Storage at path
{userId}/{timestamp}_{filename} - Generates signed URL (24-hour expiry)
- Returns path and signed URL
File: apps/backend/src/services/StorageService.ts
Database Operations
All database operations go through the repository pattern:
// BaseRepository provides:await repo.queryAll(token); // SELECT * FROM tableawait repo.queryById(id, token); // SELECT * FROM table WHERE id = ?await repo.insertRecord(data, token); // INSERT INTO tableawait repo.updateRecord(id, data, token); // UPDATE table SET ...await repo.deleteRecord(id, token); // DELETE FROM table (or soft delete)Each repository maps to a specific Supabase table:
| Repository | Table |
|---|---|
UserRepository |
profiles |
ProjectRepository |
projects |
GigRepository |
gigs |
AiHistoryRepository |
ai_history |
SocialAccountRepository |
social_accounts |
ScheduledPostRepository |
scheduled_posts |
NotificationRepository |
notifications |
SubscriptionRepository |
subscriptions |
PaymentRepository |
payments |
AnalyticsRepository |
analytics |
SettingsRepository |
settings |
ActivityLogRepository |
activity_logs |
Environment Variables
# RequiredSUPABASE_URL=https://your-project.supabase.coSUPABASE_ANON_KEY=your-anon-keySUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# FrontendPUBLIC_SUPABASE_URL=https://your-project.supabase.coPUBLIC_SUPABASE_ANON_KEY=your-anon-keyMock Mode
When SUPABASE_URL contains mock.supabase.co, the application automatically falls back to the file-based JSON database. This is useful for:
- Local development without Supabase
- Unit testing
- CI/CD pipelines

