swiftops-backend / supabase /docs /02_LOCAL_DEVELOPMENT.md
kamau1's picture
Iniital Commit
74de430

Local Development with Supabase CLI

What You'll Learn

  • How to run Supabase locally using Docker
  • How to use the Supabase CLI
  • How to sync your local database with production
  • How to test changes before deploying

Why Develop Locally?

βœ… Faster Development - No network latency
βœ… Work Offline - No internet required
βœ… Free - No usage limits
βœ… Safe Testing - Don't break production
βœ… Version Control - Track schema changes in Git


Prerequisites

1. Install Docker Desktop

Windows/Mac:

Linux:

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Start Docker
sudo systemctl start docker
sudo systemctl enable docker

2. Install Supabase CLI

Windows (PowerShell as Administrator):

# Using Scoop
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase

# Or download from GitHub releases
# https://github.com/supabase/cli/releases

Mac:

# Using Homebrew
brew install supabase/tap/supabase

# Or using npm
npm install -g supabase

Linux:

# Using npm
npm install -g supabase

# Or download binary
curl -L https://github.com/supabase/cli/releases/latest/download/supabase_linux_amd64.tar.gz | tar -xz
sudo mv supabase /usr/local/bin/

Verify installation:

supabase --version
# Should output: supabase 1.x.x

Step 1: Initialize Supabase in Your Project

Navigate to your project root:

cd swiftops-frontend

Initialize Supabase:

supabase init

This creates a supabase/ folder:

swiftops-frontend/
β”œβ”€β”€ supabase/
β”‚   β”œβ”€β”€ config.toml           # Supabase configuration
β”‚   β”œβ”€β”€ seed.sql              # Sample data for testing
β”‚   └── migrations/           # Database schema versions
β”‚       └── (empty for now)

Step 2: Start Local Supabase

Start all Supabase services locally:

supabase start

First run takes 5-10 minutes to download Docker images (~2GB).

Once started, you'll see:

Started supabase local development setup.

         API URL: http://localhost:54321
     GraphQL URL: http://localhost:54321/graphql/v1
          DB URL: postgresql://postgres:postgres@localhost:54322/postgres
      Studio URL: http://localhost:54323
    Inbucket URL: http://localhost:54324
      JWT secret: super-secret-jwt-token-with-at-least-32-characters-long
        anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Save these values! You'll need them for local development.


Step 3: Configure Local Environment

Create .env.local for local development:

# .env.local (for local development)

# Local Supabase
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Copy the anon key from `supabase start` output

Pro Tip: Create separate env files:

# .env.local - Local development
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=local-anon-key

# .env.production - Production
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=production-anon-key

Step 4: Access Local Supabase Studio

Open http://localhost:54323 in your browser.

This is your local Supabase Dashboard where you can:

  • View tables and data
  • Run SQL queries
  • Test RLS policies
  • Manage storage buckets
  • View logs

No login required for local Studio!


Step 5: Link to Remote Project (Optional)

If you want to sync with your production Supabase project:

# Login to Supabase
supabase login

# Link to your project
supabase link --project-ref your-project-id

Find your project ID:


Step 6: Deploy Your Schema Locally

Copy your schema.sql to migrations:

# Create a new migration
supabase migration new initial_schema

# This creates: supabase/migrations/20231105120000_initial_schema.sql

Copy your schema content:

# Copy your schema.sql content to the migration file
cp data/schema.sql supabase/migrations/20231105120000_initial_schema.sql

Apply the migration:

supabase db reset

This will:

  1. Drop the local database
  2. Apply all migrations
  3. Run seed data (if any)

Common CLI Commands

Start/Stop Supabase

# Start all services
supabase start

# Stop all services
supabase stop

# Stop and remove all data
supabase stop --no-backup

# Check status
supabase status

Database Management

# Reset database (drop + recreate + apply migrations)
supabase db reset

# Create a new migration
supabase migration new migration_name

# Apply migrations
supabase db push

# Generate types from database schema
supabase gen types typescript --local > types/supabase.ts

Schema Diff

# Compare local schema with remote
supabase db diff

# Generate migration from differences
supabase db diff --schema public | supabase migration new schema_changes

Testing

# Run database tests
supabase test db

# Seed database with test data
supabase db seed

Workflow: Making Schema Changes

Method 1: SQL Migrations (Recommended)

  1. Create a migration:
supabase migration new add_customer_phone
  1. Edit the migration file:
-- supabase/migrations/20231105130000_add_customer_phone.sql

ALTER TABLE customers ADD COLUMN phone_alternate TEXT;
CREATE INDEX idx_customers_phone_alternate ON customers(phone_alternate);
  1. Apply locally:
supabase db reset
  1. Test your changes in local Studio

  2. Commit to Git:

git add supabase/migrations/
git commit -m "Add alternate phone to customers"
  1. Deploy to production (see 06_MIGRATIONS.md)

Method 2: Studio + Diff (Easier for Beginners)

  1. Make changes in local Studio (http://localhost:54323)

    • Create tables
    • Add columns
    • Create indexes
  2. Generate migration from changes:

supabase db diff --schema public | supabase migration new studio_changes
  1. Review the generated migration

  2. Test by resetting:

supabase db reset
  1. Commit to Git

Seed Data for Testing

Create supabase/seed.sql for test data:

-- supabase/seed.sql

-- Create test client
INSERT INTO clients (id, name, main_email) VALUES
  ('11111111-1111-1111-1111-111111111111', 'Test Telecom', 'test@telecom.com');

-- Create test contractor
INSERT INTO contractors (id, name, main_email) VALUES
  ('22222222-2222-2222-2222-222222222222', 'Test Contractor', 'test@contractor.com');

-- Create test users (must exist in auth.users first)
-- Note: In local dev, you can create auth users via Studio or API

-- Create test project
INSERT INTO projects (
  id, 
  client_id, 
  contractor_id, 
  project_name, 
  status
) VALUES (
  '33333333-3333-3333-3333-333333333333',
  '11111111-1111-1111-1111-111111111111',
  '22222222-2222-2222-2222-222222222222',
  'Test Fiber Rollout',
  'active'
);

-- Add more test data as needed...

Load seed data:

supabase db reset  # This automatically runs seed.sql

Local Email Testing

Supabase local includes Inbucket for email testing:

  1. Open http://localhost:54324
  2. Send a magic link or OTP from your app
  3. View the email in Inbucket
  4. Click the link or copy the OTP

No real emails are sent in local development!


Environment Switching

Use different env files for different environments:

# Development (local)
npm run dev  # Uses .env.local

# Staging
npm run build && npm run start  # Uses .env.staging

# Production
npm run build && npm run start  # Uses .env.production

Or use a script:

// package.json
{
  "scripts": {
    "dev": "next dev",
    "dev:local": "cp .env.local .env && next dev",
    "dev:staging": "cp .env.staging .env && next dev",
    "build:prod": "cp .env.production .env && next build"
  }
}

Troubleshooting

Issue: "Docker is not running"

Solution:

  • Start Docker Desktop
  • Wait for it to fully start (green icon)
  • Run docker ps to verify

Issue: "Port already in use"

Solution:

# Stop Supabase
supabase stop

# Check what's using the port
# Windows
netstat -ano | findstr :54321

# Mac/Linux
lsof -i :54321

# Kill the process or change Supabase ports in config.toml

Issue: "Migration failed"

Solution:

# Check migration syntax
cat supabase/migrations/your_migration.sql

# Reset and try again
supabase db reset

# If still failing, check logs
supabase status
docker logs supabase_db_swiftops-frontend

Issue: "Can't connect to local Supabase"

Solution:

# Check if services are running
supabase status

# Restart services
supabase stop
supabase start

# Check Docker containers
docker ps

Best Practices

βœ… DO

  • Commit migrations to Git
  • Test locally before deploying
  • Use seed data for consistent testing
  • Reset database frequently during development
  • Generate TypeScript types from schema

❌ DON'T

  • Edit production database directly
  • Skip migrations and change schema manually
  • Commit .env.local to Git
  • Use production data locally (privacy/security risk)
  • Forget to stop Supabase when done (uses resources)

Docker Containers

Supabase local runs these containers:

# View running containers
docker ps

# You'll see:
# - supabase_db_* (PostgreSQL)
# - supabase_kong_* (API Gateway)
# - supabase_auth_* (Auth service)
# - supabase_rest_* (PostgREST)
# - supabase_realtime_* (Realtime service)
# - supabase_storage_* (Storage service)
# - supabase_studio_* (Studio UI)
# - supabase_inbucket_* (Email testing)

Storage location:

  • Mac/Linux: ~/.supabase/
  • Windows: %USERPROFILE%\.supabase\

Next Steps

βœ… You now have a local Supabase environment!

πŸ‘‰ Next: Read 06_MIGRATIONS.md to learn how to deploy your schema

πŸ‘‰ Or: Read 03_AUTHENTICATION.md to implement user login locally