Bỏ qua

Local Development

Tại sao cần Local Development?

Vấn đề với cloud-only development

  • Phụ thuộc internet connection
  • Chậm khi test migrations
  • Khó debug database issues
  • Tốn tiền (nếu vượt free tier)
  • Conflicts khi nhiều người cùng dev

Local development giải quyết

  • Offline development
  • Fast iteration
  • Safe testing
  • Isolated environment
  • Consistent với CI/CD

Cài đặt Supabase CLI

macOS

brew install supabase/tap/supabase

Windows (npm)

npm install -g supabase

Linux

# Download binary
curl -fsSL https://supabase.com/install.sh | sh

Verify installation

supabase --version
# Supabase CLI 1.x.x

Khởi tạo Local Project

Step 1: Init Supabase

# Trong thư mục project
supabase init

# Tạo folder structure:
# supabase/
# ├── config.toml
# ├── migrations/
# └── seed.sql

Step 2: Start services

supabase start

# Output:
# Started supabase local development setup.
#
#          API URL: http://127.0.0.1:54321
#      GraphQL URL: http://127.0.0.1:54321/graphql/v1
#           DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
#       Studio URL: http://127.0.0.1:54323
#     Inbucket URL: http://127.0.0.1:54324
#         anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Local Services

┌─────────────────────────────────────────────────────────────┐
│                    SUPABASE LOCAL                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐  Port 54323                                │
│  │   Studio    │  Database GUI (like pgAdmin)               │
│  └─────────────┘                                            │
│                                                              │
│  ┌─────────────┐  Port 54321                                │
│  │  REST API   │  PostgREST endpoints                       │
│  └─────────────┘                                            │
│                                                              │
│  ┌─────────────┐  Port 54322                                │
│  │  PostgreSQL │  Direct database access                    │
│  └─────────────┘                                            │
│                                                              │
│  ┌─────────────┐  Port 54324                                │
│  │  Inbucket   │  Email testing (catches all emails)       │
│  └─────────────┘                                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Environment Variables cho Local

# .env.local (cho local development)
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# .env.production (cho production)
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Script để switch environments

// package.json
{
  "scripts": {
    "dev": "next dev",
    "dev:local": "supabase start && next dev",
    "db:reset": "supabase db reset",
    "db:push": "supabase db push",
    "db:pull": "supabase db pull"
  }
}

Migrations

Tạo migration mới

supabase migration new create_users_table

# Tạo file: supabase/migrations/20240101000000_create_users_table.sql

Viết migration

-- supabase/migrations/20240101000000_create_users_table.sql

-- Create table
CREATE TABLE public.users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT UNIQUE NOT NULL,
  full_name TEXT,
  avatar_url TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;

-- Create policy
CREATE POLICY "Users can view own profile"
  ON public.users FOR SELECT
  USING (auth.uid() = id);

-- Create updated_at trigger
CREATE TRIGGER set_updated_at
  BEFORE UPDATE ON public.users
  FOR EACH ROW
  EXECUTE FUNCTION extensions.moddatetime(updated_at);

Apply migrations

# Apply to local
supabase db reset  # Reset và apply tất cả migrations

# Apply to remote (production)
supabase db push

Seed Data

-- supabase/seed.sql

-- Insert test users
INSERT INTO public.users (id, email, full_name)
VALUES
  ('00000000-0000-0000-0000-000000000001', 'admin@test.com', 'Admin User'),
  ('00000000-0000-0000-0000-000000000002', 'user@test.com', 'Test User');

-- Insert test posts
INSERT INTO public.posts (title, content, author_id)
VALUES
  ('First Post', 'Hello World!', '00000000-0000-0000-0000-000000000001'),
  ('Second Post', 'Testing...', '00000000-0000-0000-0000-000000000002');

Apply seed

# Reset database và apply seed
supabase db reset

# Seed chỉ chạy khi reset, không chạy khi push

Studio (Local GUI)

Truy cập Studio

http://127.0.0.1:54323

Features

  • Table Editor - GUI cho CRUD operations
  • SQL Editor - Chạy SQL queries
  • Authentication - Quản lý users
  • Storage - Upload files
  • API Docs - Auto-generated docs
  • Logs - View database logs

Inbucket (Email Testing)

Truy cập Inbucket

http://127.0.0.1:54324

Use cases

  • Test password reset emails
  • Test email verification
  • Test magic link login
  • Debug email templates

Common Commands

# Start all services
supabase start

# Stop all services
supabase stop

# Reset database (apply migrations + seed)
supabase db reset

# View status
supabase status

# View logs
supabase db logs

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

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

# Pull remote schema to local
supabase db pull

# Push local migrations to remote
supabase db push

# Diff local vs remote
supabase db diff

Workflow Development

┌─────────────────────────────────────────────────────────────┐
│                   DEVELOPMENT WORKFLOW                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  1. supabase start                                          │
│     └─▶ Start local services                                │
│                                                              │
│  2. Develop features                                        │
│     └─▶ Use local URL in .env.local                         │
│                                                              │
│  3. Create migrations                                       │
│     └─▶ supabase migration new feature_name                 │
│                                                              │
│  4. Test locally                                            │
│     └─▶ supabase db reset                                   │
│                                                              │
│  5. Commit & Push                                           │
│     └─▶ git add supabase/migrations && git commit           │
│                                                              │
│  6. Deploy to staging                                       │
│     └─▶ supabase db push --linked                           │
│                                                              │
│  7. Deploy to production                                    │
│     └─▶ CI/CD pipeline                                      │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Hands-on Exercise

Setup local development

# 1. Init supabase
supabase init

# 2. Start services
supabase start

# 3. Create first migration
supabase migration new create_tasks_table

# 4. Edit migration file
cat > supabase/migrations/*_create_tasks_table.sql << 'EOF'
CREATE TABLE public.tasks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  title TEXT NOT NULL,
  completed BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
ALTER TABLE public.tasks ENABLE ROW LEVEL SECURITY;
EOF

# 5. Apply migration
supabase db reset

# 6. Open Studio
open http://127.0.0.1:54323

# 7. Generate types
supabase gen types typescript --local > types/supabase.ts

Tổng kết

Local Development Checklist

  • [ ] Install Supabase CLI
  • [ ] Init supabase trong project
  • [ ] Start local services
  • [ ] Update .env.local với local URLs
  • [ ] Create và test migrations locally
  • [ ] Seed data cho testing
  • [ ] Use Studio cho database management

Key Commands

Command Purpose
supabase start Start local services
supabase stop Stop services
supabase db reset Reset + migrate + seed
supabase db push Push to remote
supabase gen types Generate TypeScript

Q&A

  1. Docker đã cài đặt chưa? (Required for local dev)
  2. Có vấn đề gì khi start không?
  3. Studio hoạt động tốt không?