Skip to content

整合 Supabase

本章節將帶你用 Supabase AI Prompts 和 Supabase MCP 快速整合後端。

Step 1:安裝 Supabase MCP

如果還沒安裝:

bash
claude mcp add --transport http supabase https://mcp.supabase.com/mcp

首次使用會開啟瀏覽器進行 OAuth 授權。

驗證安裝

bash
claude
/mcp

應該看到 supabaseconnected 狀態。

Step 2:設定本地 Supabase

初始化

bash
# 需要先安裝 Docker Desktop
npx supabase init

# 啟動本地 Supabase
npx supabase start

啟動後會顯示連線資訊:

API URL: http://127.0.0.1:54321
anon key: eyJhbGciOiJI...
service_role key: eyJhbGciOiJI...
Studio URL: http://127.0.0.1:54323

設定環境變數

建立 .env.local

bash
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

Step 3:用 AI Prompts 設定 Auth

這是最快的方式!直接複製 Supabase 官方的 AI Prompts。

前往官方 Prompts 頁面

supabase.com/docs/guides/getting-started/ai-prompts

複製 Auth Setup Prompt

找到「Next.js Auth Setup」的 prompt,直接複製貼到 Claude Code:

[貼上從 Supabase 文件複製的 Auth Setup prompt]

Claude 會自動建立:

  • lib/supabase/client.ts - Browser Client
  • lib/supabase/server.ts - Server Client
  • middleware.ts - Auth Middleware
  • app/login/page.tsx - 登入頁面
  • app/signup/page.tsx - 註冊頁面

官方 Prompt 範例

如果你找不到,這是類似的 prompt:

Set up Supabase Auth for my Next.js 16 project with:

1. Create Supabase client utilities:
   - lib/supabase/client.ts for browser
   - lib/supabase/server.ts for server components

2. Create middleware.ts for auth session handling

3. Create login page at app/login/page.tsx with:
   - Email/password login
   - OAuth buttons (Google, GitHub)
   - Link to signup

4. Create signup page at app/signup/page.tsx

5. Protect /dashboard routes with middleware

Use @supabase/ssr package
Use Server Actions for form handling
Use shadcn/ui components

Step 4:用 Supabase MCP 建立資料表

現在用 Supabase MCP 直接操作資料庫:

查詢現有 Schema

Show me all tables in my Supabase database

建立資料表

Create a trips table with:
- id (uuid, primary key)
- title (text, not null)
- destination (text)
- start_date (date)
- end_date (date)
- description (text)
- cover_image (text)
- user_id (uuid, references auth.users)
- created_at (timestamp with timezone)
- updated_at (timestamp with timezone)

Also create activities table with:
- id (uuid, primary key)
- trip_id (uuid, references trips)
- day (int)
- time (text)
- title (text)
- description (text)
- location (text)

Enable RLS on both tables with policies:
- Users can only see their own trips
- Users can only manage their own trips
- Activities follow trip ownership

Claude 會透過 Supabase MCP:

  1. 產生 SQL
  2. 執行 Migration
  3. 設定 RLS 政策

產生 TypeScript 型別

Generate TypeScript types for my Supabase schema

或用 CLI:

bash
npx supabase gen types typescript --local > types/database.ts

Step 5:實作 CRUD

使用 Server Components 讀取

typescript
// app/trips/page.tsx
import { createClient } from '@/lib/supabase/server';

export default async function TripsPage() {
  const supabase = await createClient();

  const { data: trips, error } = await supabase
    .from('trips')
    .select('*')
    .order('created_at', { ascending: false });

  if (error) {
    return <div>載入失敗</div>;
  }

  return (
    <div className="grid gap-4">
      {trips.map((trip) => (
        <TripCard key={trip.id} trip={trip} />
      ))}
    </div>
  );
}

使用 Server Actions 新增

typescript
// app/trips/actions.ts
'use server';

import { createClient } from '@/lib/supabase/server';
import { redirect } from 'next/navigation';

export async function createTrip(formData: FormData) {
  const supabase = await createClient();

  const { data, error } = await supabase
    .from('trips')
    .insert({
      title: formData.get('title') as string,
      destination: formData.get('destination') as string,
      start_date: formData.get('startDate') as string,
      end_date: formData.get('endDate') as string,
    })
    .select()
    .single();

  if (error) {
    throw new Error(error.message);
  }

  redirect(`/trips/${data.id}`);
}

使用 Prompt 生成完整 CRUD

請幫我建立 trips 的完整 CRUD:

1. app/trips/page.tsx - 列表頁面
2. app/trips/[id]/page.tsx - 詳情頁面
3. app/trips/new/page.tsx - 新增頁面
4. app/trips/[id]/edit/page.tsx - 編輯頁面
5. app/trips/actions.ts - Server Actions

使用:
- Server Components 讀取資料
- Server Actions 處理表單
- shadcn/ui 元件
- 遵循 CLAUDE.md 規範

Step 6:即時訂閱(可選)

如果需要即時更新:

typescript
'use client';

import { createClient } from '@/lib/supabase/client';
import { useEffect, useState } from 'react';

export function useTrips() {
  const [trips, setTrips] = useState<Trip[]>([]);
  const supabase = createClient();

  useEffect(() => {
    // 初始載入
    supabase
      .from('trips')
      .select('*')
      .then(({ data }) => setTrips(data || []));

    // 訂閱變更
    const channel = supabase
      .channel('trips')
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'trips' },
        (payload) => {
          // 處理變更
        }
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, []);

  return trips;
}

Step 7:用 Supabase MCP 除錯

查看 Logs

Show me recent error logs from my Supabase project

檢查 RLS 政策

Show me the RLS policies for the trips table

執行查詢

Query all trips created in the last 7 days

安全性提醒

重要

開發時使用本地 Supabase,不要連接 Production!

本地 vs 雲端

環境用途資料
本地 (npx supabase start)開發、測試測試資料
雲端 (supabase.com)Production真實資料

RLS 一定要啟用

sql
-- 確認 RLS 已啟用
ALTER TABLE trips ENABLE ROW LEVEL SECURITY;
ALTER TABLE activities ENABLE ROW LEVEL SECURITY;

停止本地 Supabase

bash
npx supabase stop

常見問題

連線失敗

  1. 確認 Docker Desktop 正在運行
  2. 確認 npx supabase start 成功
  3. 確認 .env.local 設定正確

RLS 導致查詢沒資料

  1. 確認已登入(有 auth.uid())
  2. 檢查 RLS 政策是否正確
  3. 開發時可以暫時用 service_role key

MCP 無法操作資料庫

  1. 確認已授權 Supabase MCP
  2. 重新執行 claude mcp add 授權
  3. 檢查 project_ref 設定

下一步

AI 時代的軟體工程工作坊教學手冊