supabase-seeding
Guides proper Supabase database seeding patterns. Use when creating seed files, seeding data, populating databases, or setting up test data in Supabase projects. Covers local and production seeding best practices.
What this skill does
# Supabase Database Seeding
Proper patterns for seeding data in Supabase projects that work locally and in production.
## Key Principle: Separate Schema from Data
**Critical:** Keep schema (tables, functions) in migrations, data in seed files.
| File Type | Contains | When Applied |
|-----------|----------|--------------|
| `migrations/*.sql` | Tables, functions, triggers, RLS policies | `db push`, `db reset` |
| `seed.sql` | INSERT statements, backfill logic | `db reset`, `db push --include-seed` |
## Setup
### 1. Configure seed.sql in config.toml
```toml
[db.seed]
enabled = true
sql_paths = ["./seed.sql"]
```
### 2. Create seed.sql
Location: `supabase/seed.sql` (same level as `migrations/`)
## Seed File Patterns
### Pattern 1: Simple Data Seeding
For basic reference data:
```sql
-- Seed: Reference Data
-- Description: Seeds initial reference data
-- Run: npx supabase db reset (local) or npx supabase db push --include-seed (production)
-- Use ON CONFLICT for idempotency (can run multiple times safely)
INSERT INTO public.categories (name, slug)
VALUES
('Technology', 'technology'),
('Science', 'science'),
('Arts', 'arts')
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name;
```
### Pattern 2: User-Dependent Seeding
When data depends on auth.users (which doesn't exist until signup):
**Step 1: Create config table in migration**
```sql
-- Migration: Create seed config infrastructure
CREATE TABLE IF NOT EXISTS public.seed_config (
email TEXT PRIMARY KEY,
config JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
```
**Step 2: Create deferred setup function in migration**
```sql
CREATE OR REPLACE FUNCTION public.apply_seed_config(p_user_id UUID, p_email TEXT)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER SET search_path = ''
AS $$
DECLARE
v_config JSONB;
BEGIN
SELECT config INTO v_config FROM public.seed_config WHERE email = p_email;
IF v_config IS NULL THEN RETURN FALSE; END IF;
-- Apply configuration to user (customize per project)
UPDATE public.profiles
SET role = v_config->>'role'
WHERE id = p_user_id;
RETURN TRUE;
END;
$$;
```
**Step 3: Hook into handle_new_user trigger in migration**
```sql
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER
LANGUAGE plpgsql
SECURITY DEFINER SET search_path = ''
AS $$
BEGIN
INSERT INTO public.profiles (id, email) VALUES (NEW.id, NEW.email);
PERFORM public.apply_seed_config(NEW.id, NEW.email);
RETURN NEW;
END;
$$;
```
**Step 4: Seed the configuration data**
```sql
-- seed.sql
INSERT INTO public.seed_config (email, config)
VALUES ('[email protected]', '{"role": "admin"}'::jsonb)
ON CONFLICT (email) DO UPDATE SET config = EXCLUDED.config;
-- Backfill for existing users
DO $$
DECLARE v_user RECORD;
BEGIN
FOR v_user IN SELECT id, email FROM auth.users LOOP
PERFORM public.apply_seed_config(v_user.id, v_user.email);
END LOOP;
END $$;
```
### Pattern 3: Domain-Based Seeding
Auto-add users by email domain:
```sql
-- Migration: Domain config table
CREATE TABLE public.domain_config (
domain TEXT PRIMARY KEY,
config JSONB NOT NULL
);
CREATE OR REPLACE FUNCTION public.apply_domain_config(p_user_id UUID, p_email TEXT)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER SET search_path = ''
AS $$
DECLARE
v_domain TEXT := split_part(p_email, '@', 2);
v_config JSONB;
BEGIN
SELECT config INTO v_config FROM public.domain_config WHERE domain = v_domain;
IF v_config IS NULL THEN RETURN FALSE; END IF;
-- Apply domain-based configuration
RETURN TRUE;
END;
$$;
```
```sql
-- seed.sql
INSERT INTO public.domain_config (domain, config)
VALUES
('company.com', '{"role": "employee"}'::jsonb),
('partner.com', '{"role": "partner"}'::jsonb)
ON CONFLICT (domain) DO UPDATE SET config = EXCLUDED.config;
```
## Commands
### Local Development
```bash
# Apply migrations only
npx supabase db push --local
# Apply migrations + seed
npx supabase db push --local --include-seed
# Full reset (DESTROYS DATA) + apply migrations + seed
npx supabase db reset
```
### Production
```bash
# Apply migrations only (safe)
npx supabase db push --project-id YOUR_PROJECT_ID
# Apply migrations + seed (careful!)
npx supabase db push --project-id YOUR_PROJECT_ID --include-seed
```
## Best Practices
### 1. Always Use ON CONFLICT
```sql
-- CORRECT - Idempotent
INSERT INTO categories (slug, name) VALUES ('tech', 'Technology')
ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name;
-- WRONG - Fails on re-run
INSERT INTO categories (slug, name) VALUES ('tech', 'Technology');
```
### 2. Use DO Blocks for Complex Logic
```sql
DO $$
DECLARE
v_record RECORD;
BEGIN
FOR v_record IN SELECT * FROM some_table LOOP
-- Complex logic here
END LOOP;
END $$;
```
### 3. Comment Your Seeds
```sql
-- Seed: Admin Users Configuration
-- Description: Sets up admin users for new signups
-- Dependencies: migrations/20240101_create_profiles.sql
-- Run: npx supabase db push --include-seed
```
### 4. Keep Seeds Idempotent
Seeds may run multiple times. Design them to be re-runnable without errors.
### 5. Separate Concerns
- **Config data** → seed.sql (emails, domains, settings)
- **Schema** → migrations (tables, functions)
- **Backfill logic** → DO blocks in seed.sql
## Common Mistakes
### Mistake 1: Tables in Seed Files
```sql
-- WRONG - Tables belong in migrations
CREATE TABLE IF NOT EXISTS public.users (...);
INSERT INTO public.users ...;
```
### Mistake 2: No Conflict Handling
```sql
-- WRONG - Will fail if data exists
INSERT INTO settings (key, value) VALUES ('theme', 'dark');
-- CORRECT
INSERT INTO settings (key, value) VALUES ('theme', 'dark')
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
```
### Mistake 3: Assuming Users Exist
```sql
-- WRONG - auth.users may be empty
INSERT INTO profiles SELECT id FROM auth.users;
-- CORRECT - Use deferred pattern with triggers
```
## File Structure
```
supabase/
├── config.toml # [db.seed] configuration
├── seed.sql # Data seeding
└── migrations/
├── 001_initial.sql
└── 002_seed_config.sql # Seed infrastructure
```
For the complete deferred seeding pattern, see [deferred-seeding.md](deferred-seeding.md).
Related in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.