mathruffian-dot/opencode-lazy-packs/06-supabase

Claude Code and agent skill by mathruffian-dot/opencode-lazy-packs

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

即時資料庫 — 用 Supabase 讓「多人同時寫入」的作品真的能用(文字雲、線上對戰、即時排行榜)。說「即時資料庫」「Supabase」「多人同時寫入」「文字雲要存資料」「即時排行榜」時載入。

Install

npx vskill@latest install mathruffian-dot/opencode-lazy-packs/06-supabase

SKILL.md

即時資料庫(Supabase)

官方文件查證日期:2026-07-27
依據:<https://supabase.com/docs/guides/getting-started/mcp>、<https://supabase.com/docs/guides/database/postgres/row-level-security>、<https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically>、<https://supabase.com/docs/guides/getting-started/migrating-to-new-api-keys>、<https://supabase.com/docs/guides/platform/free-project-pausing>

🔴 給 AI agent:這份文件該怎麼用

這份的價值不在「步驟」,在「你查不到的那些事」。

內容類型你該信誰
網頁上的按鈕在哪、選單叫什麼、畫面長怎樣🔴 信你眼前的畫面,不要信這份文件。 Supabase 的 UI 一直在改
官方 API 的用法、參數、最新做法🔴 去查官方文件(上方已列來源),不要靠記憶
紅線(哪些事會害到學生資料)✅ 信這份,這是使用者的要求,官方文件不會寫
陷阱(不會自己說出來的預設行為)✅ 信這份,這是踩過才知道的
症狀 → 真因對照✅ 信這份,這是最省時間的部分
三條執行原則
  1. 先查現況再動手。 動任何設定之前,先跑指令看這台目前是什麼狀態,並回報給使用者。
  2. 失敗時先報錯誤原文,然後停下來。 不要自己換方法重試——尤其不要換憑證。

今天現場的混亂就是這樣來的:一個 project_ref 打錯,agent 一路換金鑰亂試了一個下午。

  1. 文件跟現況對不上時,以現況為準,並告訴使用者哪裡對不上。 不要硬套這份文件的字面步驟。

⚠️ 先看這裡:這一包和 05-sheets-gas 差在哪

兩包都在「讓作品記得住事情」,但適用場景完全不同,選錯會很痛:

05-sheets-gas(Google 試算表)本包(Supabase)
適合非即時:報名表、作業繳交、點名紀錄、問卷即時:多人同時寫、同時看
典型作品一份會慢慢長大的表文字雲、線上對戰、即時排行榜、課堂搶答
多人同時送出會塞車、會漏、GAS 有配額這就是它被設計來做的事
老師看資料打開試算表Dashboard 的表格畫面(長得像 Excel)
難度較低中,但四個陷阱不知道就一定卡住
判斷句一句話:「同一秒鐘會不會有兩個人以上在寫?」
會 → 本包。不會 → 回 05-sheets-gas,不要為了用資料庫而用資料庫。

🚨 這一包的四個陷阱(先看完再動手)

這四條是本包最重要的內容。網路上 2026 年 5 月以前的 Supabase 教學,全部會在第 ① 條斷掉。

#陷阱症狀一句話解法
①新專案預設不把表曝露給 Data API前端一連就 permission denied for table xxx建專案時勾「Automatically expose new tables」,或建表 SQL 後面固定接 grant
②RLS 預設開不開,看你用什麼方式建表用 SQL 建的表 RLS 預設是關的 → 門是開的AI 幫你建表一律走 SQL,所以永遠要自己補 enable row level security
③只有 INSERT policy 不夠送出後噴紅字或畫面空白,老師以為壞了就重送 → 重複資料INSERT 和 SELECT 兩個 policy 都要建
④API key 改名了照舊教材去 Dashboard 找 anon / service_role,找不到現在叫 sb_publishable_... / sb_secret_...

下面每一步都會再點名它處理的是哪一條。


這個懶人包會幫你做什麼?

  1. 建一個 Supabase 免費專案(不用綁信用卡)
  2. 拿到可以放在網頁裡的那把金鑰
  3. 用一段貼一次就過三關的 SQL,建好一張真的能用的表
  4. 讓 GitHub Pages 上的網頁前端寫得進去、讀得回來、即時更新
  5. 用 GitHub Actions 每日排程擋掉「閒置 7 天自動暫停」
  6. (老師端進階,研習建議最後再看)把 Supabase MCP 接給 OpenCode

原理說明(30 秒)

學生的手機 ──┐
學生的手機 ──┼─→ GitHub Pages 上的網頁 ──→ Supabase(雲端資料庫)
學生的手機 ──┘ (前端) ↑
RLS 守門員
老師的 OpenCode ─────────────────────────────┘(進階,選用)

要記住的只有一件事:網頁前端拿的那把金鑰,全世界都看得到(按 F12 就看得到)。 所以資料安不安全,100% 取決於資料庫自己的守門員 RLS,跟金鑰藏得好不好完全無關。 這句話是本包所有安全設計的根。


免費方案(不用綁卡)

⚠️ 以下額度為 2026-07-27 查到的數字,服務商隨時會調整,以官方頁面為準。
項目免費方案對老師夠嗎
資料庫容量500 MB✅ 一整年的文字雲、投票遠遠用不到
同時啟用的專案數2 個⚠️ 只有 2 個,第 3 個要先暫停舊的
Realtime 同時連線200 個併發✅ 一場研習 / 一個班級夠用
信用卡不用綁✅ 研習不要求任何人自費
閒置7 天沒動作自動暫停⚠️ 見下方「步驟六」

關於暫停後還救不救得回來:官方頁面存在兩個互相矛盾的說法(一處寫 90 天內可還原,另一處提到最長 1 年)。 本包一律用保守版本教:

🔴 就當作只有 90 天。90 天內一定還原得回來,超過就不要賭。
期末做的東西如果暑假要留著,暑假前就把重要資料匯出一份放 GitHub。

先備條件

  • [ ] 已完成 `00-env-setup` 與 `01-connect-model`(沒接模型,OpenCode 不會動手)
  • [ ] 已完成 `07-github` 的第二階段(有 GitHub 帳號、會 push)——網頁要掛在 GitHub Pages,防暫停排程也要用 GitHub
  • [ ] 有網路
  • [ ] 一個瀏覽器

驗證:

powershell
gh auth status

看得到 Logged in to github.com 就過。看不到 → 回去做 `07-github`,不要在這裡臨時處理。


步驟一:建帳號與專案(🚨 這裡處理陷阱 ①)

🖐️ 全程在瀏覽器手動做。AI agent 不要代為註冊、不要代填密碼。
1-1 註冊

開 <https://supabase.com> 自己註冊,建議用 Continue with GitHub(跟 07-github 同一個帳號,之後好管理)。

按鈕文字與版面以你眼前的畫面為準,不要照這份文件找字。
1-2 建立專案

建新專案時,這四個欄位要注意(欄位名稱可能微調,看語意對應):

欄位怎麼填
Project name英數字,例如 class-live(不要中文、不要空白)
Database Password系統會產一組,直接用它產的、複製起來貼到你的密碼管理器。這組密碼研習全程用不到,但弄丟很麻煩
Region選 Northeast Asia (Tokyo) 或 Southeast Asia (Singapore),離台灣最近
Automatically expose new tables and functions🚨 把它勾起來
1-3 🚨 陷阱 ①:那個勾勾是什麼

2026-05-30 起,Supabase 新專案預設「不再自動把新建的表曝露給 Data API」。

今天建的專案已經在新預設之內。 不勾這個,後面前端一連就會拿到:

permission denied for table wordcloud.
Grant the required privileges to the current role with:
GRANT SELECT ON public.wordcloud TO anon.

而你的網頁程式碼完全沒有寫錯——這是最折磨人的地方。

兩條路,選一條(本包兩條都幫你做,雙保險):

  • A|建專案時勾起來(步驟 1-2 那個勾勾)
  • B|每次建表的 SQL 後面固定接 `grant`(步驟三的範本已經內建了)
💡 找不到那個勾勾也沒關係——走 B 就好,步驟三的 SQL 已經包含它。
反過來說:只勾了 A 就以為安全,是不夠的,因為你之後在別的地方建的表可能仍然沒被曝露。所以本包堅持 SQL 裡一定要有 grant。
1-4 驗證

專案建立要等 1~2 分鐘。左側選單看得到 Table Editor、SQL Editor、Authentication 就算好了。


步驟二:拿金鑰(🚨 這裡處理陷阱 ④)

2-1 🚨 陷阱 ④:金鑰換代了

anon 和 service_role 這兩個名字正在被淘汰。現在的名字是:

現在的名字舊名字白話能放進網頁嗎
sb_publishable_...anon可以放在網頁裡的✅ 可以,它就是設計來被看到的
sb_secret_...service_role絕對不能放的❌ 絕對不行,它會繞過所有 RLS,等於資料庫的萬能鑰匙

研習講義請只用這兩句話講,不要講 JWT、不要講 role:

Publishable key =可以放在網頁裡的。
Secret key =絕對不能放。
⚠️ 舊教材(含網路上大部分 Supabase 教學)會叫你去複製 service_role key。
本包完全不需要 secret key。 只要有人叫你把 secret key 貼進網頁、貼進 GitHub、貼給 AI,那一定是舊做法,停下來。
2-2 去哪裡拿

Dashboard 左下角 Project Settings(齒輪)→ API Keys。

複製兩個東西:

  1. Project URL(長得像 https://abcdefghijk.supabase.co)
  2. Publishable key(sb_publishable_ 開頭那一串)
如果畫面上還看得到 anon / service_role,通常是收在 Legacy API keys 分頁裡。
不要用那一區的東西,用新的 sb_publishable_...。
2-3 驗證

在 PowerShell 貼這一行(把兩個 <> 換掉):

powershell
curl.exe "<你的Project URL>/rest/v1/" -H "apikey: <你的publishable key>"
  • 回傳一段 JSON(就算內容看起來是空的 {} 或一堆 openapi 欄位)→ ✅ 金鑰是對的
  • 回 {"message":"Invalid API key"} → key 複製錯了或少了一截,重複製一次

步驟三:建表(🚨 這裡一次處理陷阱 ①②③)

3-1 🚨 陷阱 ②:這是本包最危險的一條

Supabase 官方文件白紙黑字寫的:

  • 用 Dashboard 的 Table Editor 建的表 → RLS 預設是開的
  • 用 SQL / SQL Editor 建的表 → RLS 預設是關的,要你自己開
🚨 而 AI Agent 幫你建表,一律走 SQL。

也就是說——

你對 OpenCode 說「幫我建一個成績表」,它建出來的那張表,門是開的。
不是它偷懶,是 SQL 建表本來就這樣。而沒有人會提醒你:
前端照樣讀得到寫得進去,畫面一切正常,你不會收到任何警告。
你以為做完了,實際上那張表現在全世界都能讀、能改、能刪。

所以本包的規矩是:

🔴 凡是叫 AI 建表,建完一定要自己確認 RLS 有開、policy 有建。
這件事不能外包給 AI 自己保證——要你自己看步驟 3-4 的驗證畫面。
3-2 現場範本:貼一次,過三關

Dashboard 左側 SQL Editor → New query → 整段貼上 → 右下角 Run。

sql
create table public.wordcloud (
id bigint generated always as identity primary key,
seat_no text, -- 只存座號,不存姓名
word text not null,
created_at timestamptz default now()
);
grant select, insert on public.wordcloud to anon;
grant usage, select on all sequences in schema public to anon;
alter table public.wordcloud enable row level security;
create policy "anyone can insert" on public.wordcloud
for insert to anon with check (true);
create policy "anyone can read" on public.wordcloud
for select to anon using (true);

這段 SQL 每一區在做什麼:

區塊對應陷阱白話
create table—開一張表。seat_no 只放座號
grant ... 兩行①「把這張表曝露給前端看得到」。沒有這兩行就是 `permission denied`
enable row level security②把門裝上。SQL 建表不會自己裝
for insert policy③允許寫入
for select policy③允許讀取。少了這條就會出事,見 3-3
⚠️ 這組 policy 是「研習當場、只放假資料」等級的開放設定,不是正式班務可用的設定。
with check (true) / using (true) 的意思是「任何人都可以寫、任何人都可以讀全部」。
拿它來收真實成績、真實名單,等同於公開。正式使用請先看本檔最後的「安全紅線」。
3-3 🚨 陷阱 ③:為什麼一定要有 SELECT policy

很多人以為「我只是要讓學生送資料進來,給個 INSERT policy 就好」。錯。

只給 INSERT 不給 SELECT,老師會踩到兩種狀況,兩種看起來都像壞掉:

狀況 A|前端程式碼寫成 `.insert(...).select()`(AI 幫你寫的前端十之八九是這樣,Dashboard 的範例也是這樣) Supabase 寫入後會回頭讀一次剛剛那筆,這一讀就撞到沒有 SELECT policy:

new row violates row-level security policy for table "wordcloud" (code 42501)

狀況 B|前端只寫 `.insert(...)` 不接 `.select()` 寫入沒報錯,但接下來「把大家的詞撈回來畫文字雲」的那次讀取拿到空陣列,畫面什麼都沒出現。

兩種狀況,老師看到的都是「它壞了」。而老師的直覺動作是——再送一次。 於是同一句話送三遍、五遍,資料表裡全是重複資料。

🔴 請直接背這條規則:
不要用「畫面有沒有出現東西」判斷資料進去了沒有。
要確認就去 Dashboard 的 Table Editor 打開那張表看——那裡看到的才算數。
而只要你照 3-2 的範本貼(INSERT + SELECT 兩個 policy 都有),這整件事根本不會發生。
3-4 驗證(🔴 這一步不要跳過)

驗證 1:RLS 真的開了嗎 Dashboard → Table Editor → 點 wordcloud 表。 表格上方要看到 RLS enabled(綠色)。 看到 RLS disabled / Unrestricted(紅色警告)→ 表示 alter table ... enable row level security 沒跑到,回 SQL Editor 重跑那一行。

驗證 2:policy 真的有兩條嗎 Dashboard → Authentication → Policies → 找到 wordcloud。 要看到兩條:一條 INSERT、一條 SELECT。只有一條 → 回去重跑缺的那一條。

驗證 3:純文字驗證(給 agent 判讀,也可以自己貼) 在 SQL Editor 跑:

sql
select relrowsecurity from pg_class where relname = 'wordcloud';
select policyname, cmd from pg_policies where tablename = 'wordcloud';
select has_table_privilege('anon', 'public.wordcloud', 'select') as can_read,
has_table_privilege('anon', 'public.wordcloud', 'insert') as can_write;

全部通過的樣子:

  • 第一句 → true(RLS 開著)
  • 第二句 → 兩列,cmd 分別是 INSERT 和 SELECT
  • 第三句 → can_read = true、can_write = true(陷阱 ① 過關)
3-5 要「即時更新」的話,還要多一行

前面做完,前端已經能寫、能讀。但「別人送出的詞,我這邊畫面自己跳出來」是另一件事,要另外開:

sql
alter publication supabase_realtime add table public.wordcloud;

沒跑這行的症狀:自己送自己看得到(因為是自己重新讀的),但別人送你不會動,要手動重新整理。 文字雲、線上對戰、即時排行榜都需要這一行。

驗證:

sql
select tablename from pg_publication_tables where pubname = 'supabase_realtime';

清單裡看得到 wordcloud = 過。


步驟四:網頁前端串接

前端用官方的 @supabase/supabase-js(v2)。可以直接用 CDN 的 ESM 版本 import,不用 npm、不用打包,所以放在 GitHub Pages 上就能跑。

4-1 最小可動範例
html
<script type="module">
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
// ⬇️ 這兩行本來就會被所有人看到,這是設計,不是漏洞(見最後一節)
const supabase = createClient(
'https://<你的專案id>.supabase.co',
'sb_publishable_<你的publishable key>'
)
// ① 送出一個詞
async function sendWord(seatNo, word) {
const { error } = await supabase
.from('wordcloud')
.insert({ seat_no: seatNo, word })
if (error) { alert('送出失敗:' + error.message); return false }
return true
}
// ② 讀回全部(畫文字雲用)
async function loadWords() {
const { data, error } = await supabase
.from('wordcloud')
.select('seat_no, word, created_at')
.order('created_at', { ascending: false })
if (error) { console.error(error); return [] }
return data
}
// ③ 即時:別人一送出,我這邊自己更新(需要步驟 3-5 那一行)
supabase
.channel('wordcloud-live')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'wordcloud' },
payload => {
console.log('有人送了新的詞:', payload.new.word)
// 這裡放你重畫文字雲的函式
})
.subscribe()
</script>
4-2 交給 OpenCode 做整頁的講法

不用自己寫,把下面這段貼給 OpenCode(把 `<>` 換成你自己的):

幫我做一個文字雲網頁,掛在 GitHub Pages 上。
資料庫用 Supabase:
- Project URL:<你的 Project URL>
- Publishable key:<你的 sb_publishable_...>
- 資料表:public.wordcloud,欄位 seat_no(座號,文字)、word(詞彙,文字)、created_at
功能:
1. 一個輸入框讓學生輸入「座號」和「一個詞」,按送出寫進資料庫
2. 一個按鈕切換顯示 / 隱藏文字雲
3. 用 Realtime 訂閱,別人送出的詞我這邊要自動出現,不用重新整理
4. 頁面上放這個網址的 QR Code,讓學生掃了就能進來
技術要求:
- 用 @supabase/supabase-js v2,走 CDN 的 ESM import,不要用 npm 打包
- 不要在程式碼裡放任何 secret key
- 不要收集姓名,只收座號
做完幫我 commit 並 push,然後告訴我 GitHub Pages 的網址。
⚠️ 要提醒 agent 的一句話:如果它「順手」幫你在 Supabase 建了新的表,
請它一併把步驟 3-2 那組 `grant` + `enable row level security` + 兩條 policy 補上——
這正是陷阱 ②:AI 建表走 SQL,RLS 預設是關的。
4-3 驗證(每一項都要看到)
#做什麼通過的樣子
1在網頁送出一個詞沒有紅字錯誤
2開 Dashboard 的 Table Editor → wordcloud那一列真的在裡面 ← 這才是唯一算數的證據
3關掉瀏覽器再打開網頁剛剛的詞還在(資料是存在雲端的,不是存在瀏覽器裡)
4用手機(換一個裝置、換一個網路)打開同一個網址送一個詞電腦畫面不用重新整理就自己出現 ← Realtime 通了
5按 F12 → Console沒有 permission denied 或 42501

第 4 項是這一包真正的分水嶺——做到這裡,才算做出「即時」資料庫。


步驟五:老師端怎麼看資料(不用另外做登入網頁)

Dashboard → Table Editor → 點你的表。

它長得就像 Excel:可以直接排序、篩選、改一格、刪一列、匯出 CSV。 研習現場請直接把這個畫面投影出來,老師會馬上懂「資料庫」是什麼——就是一張永遠在線上、全班可以同時寫的試算表。

匯出:表格右上角 → Export → Download as CSV。

💡 這一步之所以重要:很多人以為做資料庫一定要再做一個「老師管理後台」。
不用。 Dashboard 就是後台,而且是官方維護的。省下來的時間拿去做學生端的體驗。

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
63
Repository forks
30
7-day trend score
21

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/mathruffian-dot/opencode-lazy-packs/06-supabase/badge)](https://verified-skill.com/skills/mathruffian-dot/opencode-lazy-packs/06-supabase)

Something wrong with this skill or its page? Tell us.