Bỏ qua

Project Setup

Tạo Supabase Project

Step 1: Đăng ký tài khoản

1. Truy cập https://supabase.com
2. Sign up với GitHub
3. Tạo organization mới

Step 2: Tạo project mới

1. Dashboard → New Project
2. Điền thông tin:
   - Name: my-project
   - Database Password: (strong password)
   - Region: Singapore (ap-southeast-1)
3. Create new project
4. Đợi ~2 phút để provision

Project Credentials

Lấy credentials từ Dashboard

Project Settings → API

- Project URL: https://xxx.supabase.co
- anon (public) key: eyJhbGciOiJIUzI1NiIs...
- service_role key: eyJhbGciOiJIUzI1NiIs... (SECRET!)

Environment Variables

# .env.local (Next.js)
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...

# Server-side only (NEVER expose to client)
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIs...

Warning: KHÔNG BAO GIỜ expose service_role key ở client-side!


Cài đặt Supabase Client

Install package

npm install @supabase/supabase-js

Tạo client (Browser)

// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  );
}

Tạo client (Server)

// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export async function createClient() {
  const cookieStore = await cookies();

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll();
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            );
          } catch {}
        },
      },
    }
  );
}

Client cho Cloudflare Workers

// lib/supabase/edge.ts
import { createClient } from '@supabase/supabase-js';
import { getRequestContext } from '@cloudflare/next-on-pages';

let supabaseClient: ReturnType<typeof createClient> | null = null;

export function getSupabase() {
  if (supabaseClient) return supabaseClient;

  const { env } = getRequestContext();

  supabaseClient = createClient(
    env.NEXT_PUBLIC_SUPABASE_URL,
    env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    {
      auth: {
        persistSession: false, // Edge không có persistent storage
        autoRefreshToken: false,
      },
    }
  );

  return supabaseClient;
}

Service Role Client

Dùng cho server-side operations cần bypass RLS:

// lib/supabase/admin.ts
import { createClient } from '@supabase/supabase-js';

// ONLY use on server-side!
export function createAdminClient() {
  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!, // Bypasses RLS
    {
      auth: {
        autoRefreshToken: false,
        persistSession: false,
      },
    }
  );
}

Khi nào dùng service_role: - Migrations, seeding - Background jobs - Admin operations - Webhooks từ external services


Type Generation

Generate TypeScript types từ database

# Install Supabase CLI
npm install -g supabase

# Login
supabase login

# Generate types
supabase gen types typescript --project-id your-project-id > types/supabase.ts

Sử dụng generated types

// types/supabase.ts (generated)
export type Database = {
  public: {
    Tables: {
      users: {
        Row: { id: string; email: string; created_at: string };
        Insert: { id?: string; email: string; created_at?: string };
        Update: { id?: string; email?: string; created_at?: string };
      };
    };
  };
};

// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';
import type { Database } from '@/types/supabase';

export function createClient() {
  return createBrowserClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  );
}

// Usage - fully typed!
const { data } = await supabase.from('users').select('*');
// data is typed as Database['public']['Tables']['users']['Row'][]

Project Structure

project/
├── lib/
│   └── supabase/
│       ├── client.ts       # Browser client
│       ├── server.ts       # Server client (Next.js)
│       ├── edge.ts         # Edge client (Cloudflare)
│       └── admin.ts        # Service role client
├── types/
│   └── supabase.ts         # Generated types
├── supabase/
│   ├── config.toml         # Local dev config
│   ├── migrations/         # SQL migrations
│   └── seed.sql            # Seed data
└── .env.local              # Environment variables

Hands-on Exercise

Setup project mới

# 1. Tạo Supabase project trên dashboard

# 2. Setup trong Next.js project
npm install @supabase/supabase-js @supabase/ssr

# 3. Tạo .env.local
echo "NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co" >> .env.local
echo "NEXT_PUBLIC_SUPABASE_ANON_KEY=xxx" >> .env.local

# 4. Tạo client files (copy từ slides)

# 5. Test connection
// app/test/page.tsx
import { createClient } from '@/lib/supabase/server';

export default async function TestPage() {
  const supabase = await createClient();
  const { data, error } = await supabase.from('users').select('*').limit(1);

  return (
    <div>
      <h1>Supabase Connection Test</h1>
      {error ? (
        <p>Error: {error.message}</p>
      ) : (
        <pre>{JSON.stringify(data, null, 2)}</pre>
      )}
    </div>
  );
}

Tổng kết

Setup Checklist

  • [ ] Tạo Supabase project
  • [ ] Lưu credentials vào .env.local
  • [ ] Install @supabase/supabase-js
  • [ ] Tạo client utilities
  • [ ] Generate TypeScript types
  • [ ] Test connection

Key Points

  1. anon key = public, safe for client
  2. service_role key = secret, server-only
  3. Type generation = better DX
  4. Separate clients cho browser/server/edge

Q&A

  1. Region nào phù hợp cho dự án của bạn?
  2. Đã setup được connection chưa?
  3. Có lỗi gì không?