mono/packages/ui/docs/supabase.md
2026-02-08 15:09:32 +01:00

19 KiB

Supabase Development Guide

This guide covers common Supabase CLI operations for database migrations and TypeScript type generation.

Note: This project uses a remote-only workflow - we work directly with the remote Supabase database without running a local Supabase instance. This means all migrations are applied directly to the remote database.

Two Workflow Options: Remote-Only vs Local Development

Current Setup: Remote-Only (No Docker)

This project currently uses a remote-only workflow without Docker:

What we use:

  • npx supabase migration new - create migration files
  • npx supabase db push - apply migrations to remote
  • npx supabase gen types - generate TypeScript types from remote
  • npx supabase migration repair - fix migration history

What we DON'T use:

  • Docker Desktop
  • Local Supabase instance
  • npx supabase start
  • npx supabase db pull

Pros:

  • No Docker installation needed
  • Simpler setup (just link and go)
  • No Docker resource usage (RAM, CPU, disk)
  • Faster onboarding for new developers
  • Works on machines where Docker can't be installed

Cons:

  • Test migrations directly on remote (more risky)
  • Can't use db pull to sync from dashboard
  • Need internet connection to work
  • Slower migration testing cycle
  • No local testing environment

Alternative: Local Development with Docker (Optional)

If you install Docker Desktop, you can run a local mirror of your Supabase instance:

How it works:

  1. Install Docker Desktop

  2. Start local Supabase:

    npx supabase start
    

    This creates a complete local Supabase instance with:

    • PostgreSQL database
    • Auth server
    • Storage server
    • Realtime server
    • All accessible at http://localhost:54321
  3. Develop locally:

    # Apply migrations to LOCAL database
    npx supabase db push
    
    # Test your changes locally
    # (your app connects to localhost:54321)
    
    # Pull schema changes
    npx supabase db pull
    
    # When satisfied, push to remote
    npx supabase db push --linked
    

Pros:

  • Test migrations safely before applying to production
  • Can use db pull to sync from dashboard
  • Work offline
  • Faster migration testing
  • Complete local development environment
  • Seed data locally for testing

Cons:

  • Requires Docker Desktop (4-6 GB disk space)
  • Docker uses significant RAM (2-4 GB)
  • More complex setup
  • Need to manage two databases (local + remote)
  • Can get out of sync between local and remote

Which Should You Choose?

Stick with Remote-Only if:

  • You're working on a small project
  • You trust your SQL and test carefully
  • You want minimal setup complexity
  • Your machine can't run Docker well
  • You're new to database migrations

Switch to Local Development if:

  • You're working on a production app with users
  • You need to test complex migrations safely
  • You want to experiment without affecting production
  • You need to work offline
  • Multiple developers need isolated test environments
  • You use the Supabase dashboard and need to sync changes

How to Switch to Local Development

If you decide you want local development later:

# 1. Install Docker Desktop
# Download from: https://docs.docker.com/desktop/

# 2. Start Docker Desktop

# 3. Initialize Supabase locally
npx supabase init

# 4. Start local Supabase
npx supabase start

# 5. Apply existing migrations to local
npx supabase db push

# 6. Link to remote (if not already linked)
npx supabase link --project-ref <your-project-ref>

# 7. Now you have both local and remote!

Then you can use both:

  • npx supabase db push → applies to LOCAL database
  • npx supabase db push --linked → applies to REMOTE database
  • npx supabase db pull → pulls from remote to local migration files

Our Current Choice: Remote-Only

For this project, we're sticking with remote-only to keep things simple. But the option to add local development is always there if needs change!

Prerequisites

Linking to Remote Project

First-Time Setup

If you haven't linked your project yet, connect to your remote Supabase project:

npx supabase link --project-ref <your-project-ref>

You can find your project reference in your Supabase dashboard URL:

  • Format: https://app.supabase.com/project/<your-project-ref>
  • Example: If URL is https://app.supabase.com/project/abc123xyz, then abc123xyz is your project ref

You'll be prompted to enter your database password (the one you set when creating the project).

Verify your project is linked:

npx supabase projects list

This shows all your Supabase projects and indicates which one is currently linked.

Switching Between Projects

If you work with multiple Supabase projects:

# Link to a different project
npx supabase link --project-ref <different-project-ref>

# Or unlink current project
npx supabase unlink

Database Migrations

Creating a New Migration

Create a new migration file with a descriptive name:

npx supabase migration new <migration_name>

Example:

npx supabase migration new add_user_preferences_table

This creates a new file in supabase/migrations/ with timestamp prefix. Edit this file to add your SQL changes.

Running Migrations on Remote (Remote-Only Workflow)

For remote-only development (no local Supabase instance), apply migrations directly to your linked project:

npx supabase db push

When linked to a remote project, this command pushes migrations to your remote database.

⚠️ Important: Test migrations carefully as you're working directly with your remote database!

Checking Migration Status

See which migrations have been applied:

npx supabase migration list

Pulling Schema from Remote

⚠️ Important Note: npx supabase db pull requires Docker Desktop because it creates a local "shadow database" to compare schemas. This is a limitation of the Supabase CLI and conflicts with a true remote-only workflow.

Alternatives for Remote-Only Development:

Option 1: Don't Pull Schema (Recommended for Remote-Only)

Instead of pulling schema:

  1. Make all changes through migration files (never in the dashboard)
  2. Always create migrations for schema changes: npx supabase migration new <name>
  3. Apply migrations with: npx supabase db push
  4. This ensures your migration files are the source of truth

Option 2: Export Schema Manually

If you must capture dashboard changes, use direct SQL export:

# Get your database connection string from Supabase dashboard
# Settings > Database > Connection string (use "Direct connection")

# Then manually export schema (requires psql or pg_dump installed)
pg_dump "postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres" \
  --schema-only --schema=public > schema_export.sql

Then create a migration file from the export manually.

Option 3: Install Docker Desktop (If you really need db pull)

If you absolutely need db pull functionality:

  1. Install Docker Desktop
  2. Start Docker Desktop
  3. Then npx supabase db pull will work

But this defeats the purpose of remote-only development.

Our Recommendation for This Project:

Since we're doing remote-only development:

  • Create all schema changes via migration files
  • Never make manual changes in the Supabase dashboard
  • Use npx supabase db push to apply migrations
  • Don't use npx supabase db pull

TypeScript Type Generation

Generate Types from Remote Database

After creating or modifying database tables, regenerate TypeScript types from your remote database:

npx supabase gen types typescript --linked > src/integrations/supabase/types.ts

This command:

  1. Connects to your linked remote Supabase project
  2. Reads the current database schema
  3. Generates TypeScript types
  4. Saves them to src/integrations/supabase/types.ts

Pro tip: Run this command after every migration to keep your types in sync!

Alternative: Using Project ID Directly

If you're not in a linked project directory:

npx supabase gen types typescript --project-id <your-project-ref> > src/integrations/supabase/types.ts

Common Workflows

Workflow 1: Adding a New Table (Remote-Only)

  1. Create a migration file:

    npx supabase migration new add_my_table
    
  2. Edit the migration file in supabase/migrations/ with your SQL:

    CREATE TABLE public.my_table (
      id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
      user_id uuid REFERENCES auth.users(id) ON DELETE CASCADE,
      name text NOT NULL,
      created_at timestamp with time zone DEFAULT now()
    );
    
    -- Enable RLS
    ALTER TABLE public.my_table ENABLE ROW LEVEL SECURITY;
    
    -- Add policies
    CREATE POLICY "Users can read own data"
    ON public.my_table FOR SELECT
    USING (auth.uid() = user_id);
    
  3. Review your migration file carefully (you're going straight to remote!)

  4. Apply the migration to remote:

    npx supabase db push
    
  5. Generate TypeScript types from remote:

    npx supabase gen types typescript --linked > src/integrations/supabase/types.ts
    
  6. Commit both the migration file and updated types to git

Workflow 2: Modifying Existing Schema (Remote-Only)

  1. Create a migration:

    npx supabase migration new modify_users_table
    
  2. Add your ALTER statements in the migration file:

    -- Example: Adding a column
    ALTER TABLE public.users ADD COLUMN bio text;
    
    -- Example: Adding an index
    CREATE INDEX idx_users_email ON public.users(email);
    
  3. Review carefully (no local testing with remote-only workflow!)

  4. Apply to remote:

    npx supabase db push
    
  5. Regenerate types:

    npx supabase gen types typescript --linked > src/integrations/supabase/types.ts
    
  6. Commit migration file and updated types

Workflow 3: Handling Dashboard Changes (Remote-Only)

⚠️ Best Practice: Avoid making changes in the Supabase dashboard. Always use migration files.

If you or a teammate accidentally made changes directly in the dashboard:

Manual Migration Creation:

  1. Document what was changed in the dashboard

  2. Create a new migration file:

    npx supabase migration new sync_dashboard_changes
    
  3. Manually write the SQL that represents those changes in the migration file

  4. Apply the migration (this will fail if changes already exist, which is expected):

    npx supabase db push
    
  5. Mark the migration as applied even though it failed:

    npx supabase migration repair --status applied <migration-timestamp>
    
  6. Regenerate types:

    npx supabase gen types typescript --linked > src/integrations/supabase/types.ts
    
  7. Commit the migration file and updated types

Better Approach: Establish a team rule to never make manual changes in the dashboard.

Workflow 4: Quick Deploy Script

Use the existing deploy script for a complete deployment:

bash scripts/supabase-deploy.sh

This script (from scripts/supabase-deploy.sh):

  1. Deploys Mux proxy edge function
  2. Pushes all pending database migrations
  3. Regenerates TypeScript types from remote schema

Troubleshooting

Types Not Updating

If types don't reflect your changes:

  1. Ensure migration was applied:

    npx supabase migration list
    
  2. Try regenerating with explicit project ref:

    npx supabase gen types typescript --project-id <your-project-ref> > src/integrations/supabase/types.ts
    

Migration Conflicts

If you have migration conflicts:

  1. Check the migration order in supabase/migrations/
  2. Ensure timestamps are correct
  3. Consider creating a new migration to fix issues rather than editing old ones

Database Out of Sync

If your migration files are out of sync with the remote database:

Remote-Only Approach:

  1. Review what's in your supabase/migrations/ directory
  2. Check what's actually in the remote database (via Supabase dashboard > Table Editor)
  3. Create a new migration to fix the differences:
    npx supabase migration new fix_sync_issue
    
  4. Write SQL in the migration file to align remote with what you want
  5. Apply the migration:
    npx supabase db push
    

Note: Without db pull (which requires Docker), you need to manually track what's in your database vs. your migration files.

Migration History Mismatch

If you get an error like "The remote database's migration history does not match local files":

This happens when:

  • Migration files were deleted/modified locally but the remote database still has records of them
  • Team members have different migration files
  • The migration history table is out of sync

Solution 1: Repair Migration History (Recommended)

The CLI will suggest repair commands. You can run them all at once using the provided script:

# Linux/Mac:
bash scripts/repair-migrations.sh

# Windows PowerShell:
.\scripts\repair-migrations.ps1

This script runs all the repair commands to sync your migration history table.

Or run them manually one by one:

# Copy all the suggested repair commands from the error output
# Example:
npx supabase migration repair --status reverted 20250927012218
npx supabase migration repair --status applied 20250119000001
# ... etc

Solution 2: Clean Slate Approach

If you have many migrations to repair and want to start fresh:

  1. Backup first! Make sure you have your migration files in git

  2. Decide on your source of truth:

    • Option A: Your migration files are correct → just repair them all
    • Option B: Remote database is correct → delete old migration files and create new ones
  3. For Option B (remote is correct):

    • Delete old migration files that don't match remote
    • Manually inspect the remote schema in Supabase dashboard
    • Create new migration files that represent the current state
    • Mark them as applied:
      npx supabase migration repair --status applied <migration-timestamp>
      
  4. Regenerate types:

    npx supabase gen types typescript --linked > src/integrations/supabase/types.ts
    

Solution 3: Manual Cleanup

If you know which migrations should be kept:

  1. Check your supabase/migrations/ directory
  2. Delete any migration files that shouldn't be there
  3. Run the repair commands for the remaining ones
  4. Regenerate types:
    npx supabase gen types typescript --linked > src/integrations/supabase/types.ts
    

Understanding the Output:

  • --status reverted = Migration file exists locally but not applied in remote (or was rolled back)
  • --status applied = Migration was applied in remote

After running the repair commands, your migration history should be in sync.

Authentication Issues

If you get authentication errors:

  1. Re-link your project:

    npx supabase link --project-ref <your-project-ref>
    
  2. Verify you're using the correct database password

  3. Check your internet connection

Best Practices (Remote-Only Workflow)

  1. Review migrations carefully before pushing - you're working directly on remote, so double-check your SQL!
  2. Regenerate types after every schema change to keep TypeScript in sync
  3. Use descriptive migration names (e.g., add_video_comments_table not update)
  4. Always commit migration files AND updated types.ts together in the same commit
  5. Use npx supabase db pull after any manual dashboard changes to capture them as migrations
  6. Enable RLS on new tables unless you have a specific reason not to
  7. Add appropriate indexes for foreign keys and frequently queried columns
  8. Use transactions in migrations when making multiple related changes
  9. Test in a staging environment if possible before applying to production
  10. Keep your project linked - verify with npx supabase projects list

Quick Reference Commands (Remote-Only)

# Link to your Supabase project (first time setup)
npx supabase link --project-ref <your-project-ref>

# Check which project is linked
npx supabase projects list

# Create new migration file
npx supabase migration new <descriptive_name>

# Apply migrations to remote database
npx supabase db push

# Check migration status
npx supabase migration list

# Generate TypeScript types from remote
npx supabase gen types typescript --linked > src/integrations/supabase/types.ts

# Deploy everything (migrations + types + edge functions)
bash scripts/supabase-deploy.sh

# Repair migration history (if needed)
bash scripts/repair-migrations.sh  # Linux/Mac
.\scripts\repair-migrations.ps1     # Windows PowerShell

Note: We don't use npx supabase db pull because it requires Docker Desktop, which defeats the remote-only workflow.

Example: Complete Workflow from Start

# 1. Link your project (one-time setup)
npx supabase link --project-ref abc123xyz

# 2. Create a migration
npx supabase migration new add_comments_table

# 3. Edit the migration file in supabase/migrations/
# (Use your code editor to add SQL)

# 4. Push migration to remote
npx supabase db push

# 5. Regenerate types
npx supabase gen types typescript --linked > src/integrations/supabase/types.ts

# 6. Commit your changes
git add supabase/migrations/* src/integrations/supabase/types.ts
git commit -m "Add comments table"
git push

References