開發過程中常見問題的集中解答。
Spectra 適合複雜功能(3+ 個檔案變更、需追蹤規格演進、多人協作),提供三階段流程(propose → apply → archive)與完整歸檔。Plan Mode 適合小修改、需求明確的場景。Bug 修復或緊急部署可直接實作。
詳細比較與指令說明請參考 OPENSPEC.md。
用途:將 docs/ 目錄的 Markdown 轉換為可瀏覽的文件網站。
為什麼要用?
- 方便分享給團隊成員
- 提供搜尋功能
- 更好的閱讀體驗
命令:
pnpm docs:dev # 本地預覽(http://localhost:5173)
pnpm docs:build # 建置靜態網站目前狀態:使用 VitePress 預設配置。如需客製化,可建立 .vitepress/config.ts。
兩種 Skill 類型:
| 類型 | 數量 | 更新方式 |
|---|---|---|
| 通用 Skills | 26 個 | 全部第三方,pnpm skills:update 自動更新 |
| 情境 Skills | 5 個 | 本地維護,手動更新 |
| SDD Skills | 12 個 | Spectra(spectra-*) |
第三方 Skills 更新流程:
- 執行
pnpm skills:update(使用 skills.sh CLI) - 從各 GitHub repo 拉取最新版本
- 更新到
.claude/skills/目錄 - 重啟 Claude Code CLI
情境 Skills 何時需要更新?
- 專案架構變更時
- 發現更好的實踐模式時
- RLS/Migration 規則調整時
推薦方案:Claude Code Max(每月 $100 美元起)
為什麼?
本專案大量使用 Claude Opus 模型進行:
- 複雜的程式碼生成與重構
- 多檔案同時編輯
- 資料庫 migration 設計
- Spectra 結構化開發
| 方案 | 每月費用 | Opus 用量 | 適合 |
|---|---|---|---|
| Pro | $20 | 有限 | 輕度使用、學習 |
| Max 5x | $100 | 充足 | 日常開發(推薦) |
| Max 20x | $200 | 大量 | 密集開發、團隊共用 |
實際經驗:密集開發時 Pro 方案會頻繁遇到 Opus 配額限制,被迫切換到 Sonnet 模型。Max 5x 方案足以支撐日常開發。
| 類型 | 觸發方式 | 用途 | 範例 |
|---|---|---|---|
| Commands | 使用者輸入 /xxx |
執行特定流程 | /commit, /db-migration, /spectra-propose |
| Agents | 自動觸發或被 Command 呼叫 | 執行子任務 | check-runner, code-review, db-backup |
| Skills | 自動偵測情境載入 | 提供專業知識 | supabase-rls, server-api |
類比:
- Commands = 你下達的指令
- Agents = 執行指令的機器人
- Skills = 機器人的專業知識
核心原則:Client 讀、Server 寫
| 操作 | 位置 | 方式 |
|---|---|---|
| 讀取 | Client | useSupabaseClient<Database>().from('table').select() |
| 寫入 | Server | $fetch('/api/v1/resources', { method: 'POST', body }) |
為什麼?
- RLS 已保護讀取操作
- 寫入需要集中管理(權限檢查、日誌、業務邏輯)
- 讀多寫少,Client 直連減少延遲
詳細說明:見 CLAUDE.md
正確方式:
// Client 端
const { user, loggedIn, signIn, signOut } = useUserSession()
// Server 端
// 使用 better-auth 提供的方式取得 session錯誤方式(絕對禁止):
// ❌ 這是舊的 Supabase Auth,本專案不使用
const user = useSupabaseUser()
const user = await serverSupabaseUser(event)詳細說明:見 AUTH_INTEGRATION.md
Local-First 原則:所有 migration 必須先在本地建立、測試通過後,再 push 到 remote。
# 1. 建立 migration
supabase migration new add_user_roles
# 2. 編輯 migration 檔案(在 supabase/migrations/ 下)
# 3. 本地測試
pnpm db:reset
# 4. 安全檢查
pnpm db:lint
# 5. 重新產生類型
pnpm db:types
# 6. 最後才 push
supabase db push禁止事項:
- ❌ 不要手動建立
.sql檔案 - ❌ 不要用
mcp__remote-supabase__apply_migration - ❌ 不要修改已套用的 migration
詳細說明:見 SUPABASE_MIGRATION_GUIDE.md
關鍵重點:API 寫入操作的 RLS policy 必須包含 service_role 繞過!
CREATE POLICY "Allow manager update" ON your_schema.table FOR UPDATE
USING (
(SELECT auth.role()) = 'service_role' -- ⚠️ 必須加這行!
OR your_schema.current_user_role() IN ('admin', 'manager')
);詳細說明:見 RLS_BEST_PRACTICES.md
必須使用空字串:
CREATE OR REPLACE FUNCTION your_schema.my_function()
RETURNS void LANGUAGE plpgsql SECURITY DEFINER
SET search_path = '' -- 必須是空字串!
AS $$ BEGIN
SELECT * FROM your_schema.users WHERE id = auth.uid();
END; $$;禁止:SET search_path = public, pg_temp
原因:缺少對應的 RLS policy
解決:
- 檢查是否有該操作(INSERT/UPDATE/DELETE)的 RLS policy
- 確認 policy 包含
service_role繞過 - 使用
pnpm db:lint檢查
📖 完整診斷:TROUBLESHOOTING.md
原因:路由衝突
常見情況:同目錄下同時存在 [id].ts 和 [id]/xxx.ts
解決:調整路由結構,避免衝突
📖 完整診斷:TROUBLESHOOTING.md
原因:可能是 format、lint、typecheck 或 test 任一環節失敗
解決:
- 看錯誤訊息判斷是哪個環節
- 逐一修復
- 重新執行
pnpm check
各環節單獨執行:
pnpm format # 格式化
pnpm lint # Lint 檢查
pnpm typecheck # 類型檢查
pnpm test # 測試📖 完整診斷:TROUBLESHOOTING.md
檢查清單:
- Docker 是否在運行?
- 執行
supabase status確認服務狀態 - 檢查
.env的SUPABASE_URL是否正確(應為http://127.0.0.1:54321)
重啟方式:
supabase stop
supabase start📖 完整診斷:TROUBLESHOOTING.md
原因:app/types/database.types.ts 可能過時或不存在
解決:
pnpm db:types📖 完整診斷:TROUBLESHOOTING.md
快速決策:
| 情境 | 推薦 |
|---|---|
| 純資料庫操作 | RPC |
| 需要外部 API 呼叫 | Edge Function |
| 需要複雜業務邏輯 | Edge Function |
| 效能敏感的查詢 | RPC |
| 需要檔案處理 | Edge Function |
詳細決策樹:見 .claude/skills/supabase-arch/SKILL.md
核心原則:
- 使用 Composition API 風格
- State 使用
readonly()保護 - 透過 actions 修改 state
本專案設定 ssr: false(SPA 模式),原因:
- 部署目標:Cloudflare Workers 免費方案 CPU 時間僅 10ms,SSR 會消耗寶貴資源
- 應用類型:定位為「登入後的管理系統」,不需要 SEO
- 開發簡化:避免 hydration mismatch、SSR 相容性等問題
如果你的專案需要 SEO(如部落格、電商),可將 nuxt.config.ts 中的 ssr 改為 true。
Vite+ 將 test / lint / fmt / hooks 統一到 vite.config.ts,底層使用 OXC 工具鏈(Rust 編寫),lint 速度是 ESLint 的 50-100 倍。一個 vp check 指令取代多個獨立工具。
Pinia 是狀態管理(類似 Vuex),Pinia Colada 是 Pinia 的非同步資料管理層(類似 TanStack Query)。
- Pinia:管理本地狀態(使用者偏好、UI 狀態等)
- Pinia Colada:管理 Server 資料(自動快取、stale 管理、mutation + invalidation)
本專案兩者搭配使用:Pinia 管理 client state,Colada 管理 server state。Colada 由 Pinia 作者開發,API 風格一致,與 Vue DevTools 無縫整合。
本專案使用 Nuxt UI v3(@nuxt/ui v3.x,基於 Tailwind CSS v4 + Reka UI)。
| 面向 | Nuxt UI v2 | Nuxt UI v3(本專案) |
|---|---|---|
| CSS 框架 | Tailwind CSS v3 | Tailwind CSS v4 |
| 底層元件 | Headless UI | Reka UI |
| 主題系統 | app.config.ts |
CSS 變數 + Tailwind |
| Vue 版本 | Vue 3 | Vue 3 |
注意:v2 和 v3 的元件 API 有差異,搜尋教學時請確認是 v3 版本的文件。Nuxt UI 官方文件:ui.nuxt.com
本專案的功能是模組化的,可按需移除:
不需要 Supabase(純前端):
- 移除
@nuxtjs/supabase和@supabase/supabase-js - 從
nuxt.config.ts移除 supabase 模組 - 刪除
supabase/目錄和server/utils/supabase.ts - 刪除
app/types/database.types.ts
不需要認證:
- 移除
better-auth和@onmax/nuxt-better-auth - 從
nuxt.config.ts移除 betterAuth 模組 - 刪除
app/auth.config.ts和server/auth.config.ts
不需要 AI 工具:
- 刪除
.claude/目錄 - 刪除
.agents/目錄 - 刪除
openspec/和.spectra/目錄 - 核心 Nuxt + Supabase 功能不受影響
不需要 Sentry:
- 移除
@sentry/nuxt - 從
nuxt.config.ts移除 sentry 模組配置
推薦方式:使用 WSL 2(Windows Subsystem for Linux)。
原因:
- Docker(Supabase 需要)在 WSL 2 上運行最穩定
- Shell 腳本(
setup.sh等)原生支援 - 與 Linux/macOS 開發環境一致
步驟:
- 安裝 WSL 2:
wsl --install - 安裝 Docker Desktop 並啟用 WSL 2 整合
- 在 WSL 中安裝 Node.js、pnpm、Supabase CLI
- 按照 README 正常操作
不用 WSL 也可以嗎? scripts/setup.sh 有偵測 Windows 環境的邏輯,但某些功能可能需要手動調整。建議優先使用 WSL 2。
📖 故障排除:TROUBLESHOOTING.md
執行 scripts/setup.sh,自動完成:
- 檢查先決條件(Node 20+、pnpm、Docker、Supabase CLI)
- 安裝依賴(
pnpm install) - 複製
.env.example→.env(若不存在) - 啟動本地 Supabase
- 產生資料庫型別
📖 故障排除:TROUBLESHOOTING.md
Supabase 的 Docker 映像已支援 ARM64 架構,但偶爾可能遇到:
- 映像下載慢:正常現象,首次下載需較長時間
- 記憶體不足:Docker Desktop → Settings → Resources → 至少分配 4GB RAM
- 容器啟動失敗:嘗試
docker system prune清理後重新supabase start
📖 診斷步驟:TROUBLESHOOTING.md
可以。只需設定 BETTER_AUTH_SECRET 和 NUXT_SESSION_PASSWORD,OAuth 相關的環境變數留空即可。登入頁面會自動隱藏未設定的 OAuth 按鈕。
不會明顯影響。RLS 政策在 PostgreSQL 內部以 WHERE 子句形式執行,走索引路徑。實測 RLS 開啟/關閉的差異通常在 1-2ms 以內。
最佳化建議:
- 確保 RLS 條件欄位有索引(例如
user_id) - 避免在 RLS 政策中使用子查詢,改用
auth.uid()直接比較 - 使用
EXPLAIN ANALYZE確認查詢計畫
📖 詳細說明:DATABASE_OPTIMIZATION.md
N+1 問題通常出現在逐筆查詢關聯資料。偵測方式:
# 檢查 Supabase 慢查詢 log
pnpm db:lint修復模式:使用 .select('*, relation(*)') 一次取回關聯資料,避免迴圈中逐筆查詢。
📖 診斷步驟:TROUBLESHOOTING.md
| 資源 | 免費方案限制 |
|---|---|
| 資料庫大小 | 500 MB |
| 頻寬 | 5 GB / 月 |
| 儲存空間 | 1 GB |
| Edge Functions | 500K 次調用 / 月 |
| 同時連線數 | 60 |
對大多數 MVP 和小型產品足夠。超過限制時可升級到 Pro 方案($25/月),或 Self-host Supabase(開源免費),完全不受以上限制。
- Supabase Cloud:升級到 Pro($25/月),包含 8GB 資料庫、250GB 頻寬、100GB 儲存
- Supabase Self-hosted:Supabase 是開源的,可以免費自架在自己的伺服器上,不受任何方案限制。詳見 Self-hosted 部署指南
- Cloudflare Workers:免費方案包含 10 萬次請求/天,超過後 $5/月(無限請求)
- 漸進升級:先用免費方案開發,接近限制時再升級或改用 Self-hosted,無需改動程式碼
免費方案包含:
- 每天 100,000 次請求
- 每次請求 10ms CPU 時間
- 全球邊緣部署
對大多數小型應用完全足夠。付費方案($5/月)提供無限請求和更多 CPU 時間。
規則:
- 每個功能在獨立 branch 開發,各自建立 migration
- Migration 檔名帶時間戳(
supabase migration new自動處理) - 合併前執行
pnpm db:reset確認所有 migration 可正常套用 - 若遠端已有衝突的 migration,使用
supabase migration repair --status reverted <version>處理
📖 診斷步驟:TROUBLESHOOTING.md
檢查清單:
- Migration 檔案包含
SET search_path = ''(如有函式) - RLS 政策包含
service_rolebypass - Client 端只有
.select()讀取,寫入走 Server API - 新增環境變數同步更新
.env.example -
pnpm check通過(format + lint + typecheck + test) - docs/verify/ 相關文件已更新
建議閱讀順序(約 1 小時):
- README.md(5 分鐘)— 了解專案定位
- WORKFLOW.md(10 分鐘)— 開發流程
- FAQ.md(10 分鐘)— 常見問題
- API_PATTERNS.md(15 分鐘)— API 設計模式
之後按需查閱 docs/verify/ 的參考手冊。
- 搜尋
docs/目錄的其他文件 - 查看 CLAUDE.md 的相關章節
- 使用 Claude Code 詢問(它會參考專案的 Skills 和規範)