新版舊版
0 基礎做一個有後端+資料庫的網頁
進階版 · 訪客留言板實戰 · Next.js + Supabase + 環境變數
黃志弘 Leo
2026-06-26 發佈 · 2026-10-07 更新 · 249 人看過
做一個真的能存留言的訪客留言板
這是基礎版的下一步。基礎版做的是「只有畫面」的一頁式網頁;這篇要做一個會把訪客留言存進資料庫的網頁,也就是一個訪客留言板。做完你就懂三個讓網頁「活起來」的關鍵:後端 API、雲端資料庫、環境變數。一樣全程跟 Claude 講中文,11 個 prompt 照貼。
預計時間:3 - 5 小時
基礎花費:Claude Pro USD 20 / 月(Supabase + Vercel 免費)
需要:桌面電腦(Mac / Win)
程度:建議先做過基礎版
真實案例:這篇的留言板我真的做了一份、也部署上線、實際留言驗證過存得進資料庫。下面每一個 prompt、每一步驟都是照著那份跑出來的,不是憑空寫的。2026 年 10 月 Supabase 換了金鑰制度,所以取金鑰的地方我重新寫過,指令也在自己的電腦跑了一次。終端機是當天的真實畫面,Supabase 金鑰頁跟 Vercel 環境變數這兩張是示意圖,其他都是我當初做的時候截的。
先決條件:這篇假設你已經會基礎版那套(裝好 Claude Code、有 GitHub / Vercel 帳號、知道怎麼 push 跟部署)。如果還沒,先去看基礎版把手感練起來再回來,會順很多。
這次會多用到三樣東西:後端 API、資料庫、環境變數
基礎版的網頁是「死的」,做好就固定在那,訪客只能看。這篇的網頁是「活的」,訪客可以送資料進來、存起來、下次還在。差別就在這三樣:
| 能力 | 基礎版(靜態) | 這篇(有後端) |
|---|---|---|
| 顯示文字圖片 | ✓ | ✓ |
| 訪客送資料進來 | ✕ 做不到 | ✓ 留言表單 |
| 把資料存起來 | ✕ 沒有資料庫 | ✓ 存進 Supabase |
| 保管金鑰 | 不需要 | ✓ 用環境變數 |
後端 APIbackend
基礎版的網頁全部跑在「訪客的瀏覽器」裡。後端 API 是一段跑在「雲端伺服器」上的程式,它負責接收留言、決定要不要存、再去操作資料庫。瀏覽器看不到它的內容,所以碰資料庫、用金鑰這些事都交給它做。
資料庫database
放資料的地方,這篇用 Supabase(免費、好上手)。訪客每留一則言,就變成資料庫裡的一筆紀錄,永久存著,重新整理、換裝置都還在。
環境變數environment variables
連資料庫要用「金鑰」。金鑰不能寫死在程式碼裡、更不能推上 GitHub(等於公開鑰匙)。環境變數就是把金鑰放在一個不會被上傳的檔案裡。AI 寫程式最常犯的資安錯就是這個,這篇會教你正確做法。
註冊 Supabase,建好第一個專案
Claude Code、GitHub、Vercel 沿用基礎版那套就好。這篇只多一個新帳號要辦:Supabase(你的雲端資料庫)。
0-1註冊 Supabase
Supabase 是免費、好上手的雲端資料庫平台。最快的註冊方式是用你的 GitHub 帳號登入。
- 到 supabase.com,右上角按 Start your project
- 選 Continue with GitHub(跟註冊 Vercel 一樣,授權一下就好)
- 進去後按 New project(或直接開 database.new),取個名字(例如
my-guestbook)、設一組資料庫密碼(隨機產生、存起來就好,這篇用不太到)、地區選離你近的(例如 Singapore) - 等個一兩分鐘,專案就建好了
按鈕名稱對不上的話:Supabase 首頁的按鈕文字偶爾會改,找「註冊」或「建立專案」意思的按鈕就對了。免費方案最多同時開 2 個專案,而且專案連續一週沒有人用會被暫停(官方方案頁寫的規則,查證 2026-10-07)。
準備完成檢查表:☐ Claude Code 打
claude 有反應 ☐ 能登入 GitHub ☐ 能登入 Vercel ☐ 能進 Supabase 看到剛建好的專案。四個都勾,就往下走。11 個 prompt:跟 Claude 聊出一個會存資料的網頁
跟基礎版一樣,把每個 prompt 照順序貼到 Claude Code,看它做完按 Enter,再貼下一個。每個 prompt 右上角都有複製按鈕。先在 Terminal 切到放專案的資料夾(例如 cd ~/Projects)再打 claude。
第 1 步用 Next.js 建好留言板專案(1 個 prompt)
基礎版用純 HTML;這篇要有後端,所以用 Next.js(一個前後端都能寫的框架,Vercel 原生支援)。你不用懂它,講一句就好。
Prompt 1 建留言板專案
幫我用 Next.js 建一個專案叫 my-guestbook,我要做一個訪客留言板:有一個留言表單,送出後留言會存起來、顯示在下面。先把專案建好、能在本機跑起來就好。Claude 會做:用
create-next-app 建好專案、裝好套件,終端機最後會出現一行 Success! Created my-guestbook,再跟你說怎麼用 npm run dev 在本機 localhost:3000 打開。這時候畫面還是 Next.js 的預設頁,正常。卡住的話:如果跳出
npx: command not found,代表電腦還沒裝 Node.js。跟 Claude 說「幫我裝 Node.js」,裝好再貼一次 Prompt 1。第 2 步接上 Supabase,建一張放留言的表(2 個 prompt)
把專案連到你剛剛建的 Supabase,然後開一張「桌子」(資料表)來放留言。
Prompt 2 裝 Supabase 工具
幫我裝 Supabase 的官方套件 @supabase/supabase-js,等下我要用它把留言存進資料庫。Claude 會做:跑
npm install @supabase/supabase-js,這是 Supabase 官方的連線工具。終端機出現一行 added 8 packages 左右的訊息就裝好了(數字會隨版本變,看到 added 就對了)。Prompt 3 建留言資料表
我的 Supabase 要一張表叫 guestbook 放留言,欄位有:名字、留言內容、建立時間。給我一段 SQL,我去 Supabase 的 SQL Editor 貼上執行。記得幫我開 RLS(Row Level Security),並加上「任何人都能讀、任何人都能新增留言」的政策,也要明確 grant 讀取跟新增的權限給 anon 角色。你要做:Claude 會給你一段 SQL(像下面這樣)。複製起來,到 Supabase 左邊選單的 SQL Editor,貼上,按 Run,下方結果區出現「Success. No rows returned」就是建好了(這段 SQL 本來就不會回傳資料)。
create table guestbook (
id bigint generated always as identity primary key,
name text not null,
message text not null,
created_at timestamptz not null default now()
);
grant select, insert on public.guestbook to anon;
alter table guestbook enable row level security;
create policy "anyone can read" on guestbook
for select to anon using (true);
create policy "anyone can insert" on guestbook
for insert to anon with check (true);RLS 是什麼、為什麼重要:Row Level Security 是資料庫的「門禁」。開了 RLS 但不寫政策,整張表就鎖死,誰都進不去。所以一定要配一條政策說明「誰可以做什麼」。留言板我們只開放「大家都能讀、都能新增」,但沒開放刪除跟修改,這樣別人不能改掉或刪掉留言。這就是資安的第一課:預設全鎖,再一條條開。
多出來的那行 grant:沒有這行 grant 的話,就算 RLS 政策寫好了,還是可能沒有權限讀寫資料。以前新建的表會自動給權限,Supabase 官方文件說正在把這個預設改掉,所以這裡自己加上去比較保險。這段 SQL 我在本機的 Supabase 跑過一次,每一行都順利執行。如果你之後看到
42501、permission denied for table guestbook 這種錯誤,就是少了這行 grant,把錯誤訊息貼給 Claude,它會補上。
guestbook 表(這是我實際跑出來的資料)。第 3 步拿 Project URL 和 publishable key,放進 .env.local(2 個 prompt)
這是這篇最重要、也最容易被 AI 寫錯的一段。要連資料庫得有兩個東西:你的 Project URL 跟一把 publishable key。我們把它們放進一個不會被上傳的檔案。
Supabase 的金鑰換新制了:官方文件寫明,舊的
anon 和 service_role 金鑰會在 2026 年底停用,改用 publishable key(sb_publishable_ 開頭)和 secret key(sb_secret_ 開頭)。新金鑰是一段短字串。如果你看到教學叫你複製 eyJ 開頭的長金鑰,那是舊版的寫法,這篇改用 sb_publishable_ 開頭的 key。到 Supabase 複製這兩個值
打開你的 Supabase 專案,下面兩個地方都拿得到,選一個就好:
- 專案的 Connect 對話框:框架選 Next.js,它會直接列出 Project URL 和 publishable key,照著複製。
- Project Settings → API Keys:所有金鑰都放在這一頁。Project URL 在 Connect 對話框裡也看得到。如果教學寫的是「Settings → API」,那個頁面已經拿掉了,改到 API Keys 這一頁找。
卡住的話:如果 API Keys 頁只看得到舊的 anon 跟 service_role,代表這個專案還沒有新金鑰。官方文件的做法是在同一頁建立一把 publishable key,舊金鑰不會因此失效,兩套可以同時存在。
Prompt 4 設定環境變數檔
幫我在專案根目錄建一個 .env.local 檔,裡面放兩個環境變數 SUPABASE_URL 跟 SUPABASE_PUBLISHABLE_KEY。先用佔位值,我等下自己貼真的進去。順便確認 .gitignore 有把 .env.local 排除掉,不要被推上 GitHub。Claude 會做:建好
.env.local,並確認 .gitignore 有 .env* 這行。Next.js 建專案時預設就有,所以金鑰天生就不會被上傳。想自己確認,可以在終端機打 git check-ignore -v .env.local,有印出 .env.local 就代表它被擋住了:
.env.local,代表 git 不會把它推上 GitHub。然後你把剛剛複製的兩個值貼進去,.env.local 長這樣:
SUPABASE_URL=https://你的專案代號.supabase.co
SUPABASE_PUBLISHABLE_KEY=sb_publishable_...(你複製的那一串)Supabase 官方範例裡,給瀏覽器用的變數前面會加
NEXT_PUBLIC_。這篇的金鑰只在後端 API 裡讀,所以不加,Next.js 就不會把它打包進網頁。這一步就是 AI 最容易踩雷的地方:很多人(跟很多 AI)會圖方便,直接把金鑰寫死在程式碼裡,然後 push 上 GitHub,等於把鑰匙公開貼在網路上。正確做法永遠是:金鑰放
.env.local、確認被 .gitignore 排除、程式碼裡只用 process.env.SUPABASE_URL 這種「名字」去讀。貼之前可以反問 Claude 一句「我的金鑰會不會被推上 GitHub?」讓它幫你再檢查一次。第 4 步讓 Claude 寫後端 API 和留言畫面(2 個 prompt)
後端負責「碰資料庫」,前端負責「給訪客看跟填」。分開讓 Claude 寫。
Prompt 5 後端 API(讀寫留言)
幫我寫一個後端 API:一個負責新增留言(把名字、留言寫進 Supabase 的 guestbook 表),一個負責讀出所有留言(依時間新到舊)。連線用環境變數 SUPABASE_URL 跟 SUPABASE_PUBLISHABLE_KEY,這段程式只在伺服器端跑、不要把金鑰送到瀏覽器。也幫名字跟留言長度做基本檢查,避免空白或太長。Claude 會做:建一個 API route(例如
app/api/guestbook/route.ts),用 process.env 讀金鑰、連 Supabase 做新增跟查詢,並擋掉空白/過長的輸入。Prompt 6 前端(表單 + 留言列表)
幫我做留言板的畫面:上面一個表單(填名字、留言、送出鈕),送出後呼叫剛剛的 API,成功就清空欄位並刷新;下面照時間新到舊列出所有留言,每則顯示名字、內容、時間。風格走乾淨簡約、暖色奶油底配金色重點,手機上也要好看。Claude 會做:做出表單跟留言列表,串好 API。這時候本機畫面就會長下面這樣。
localhost:3000 跑起來的樣子:表單在上、留言在下,乾淨簡約。這是我實際跑出來的畫面。第 5 步在本機送一則留言,確認真的存進去(1 個 prompt)
上線前先在自己電腦上確認真的會存。
Prompt 7 跑起來測一則留言
幫我在本機把網站跑起來,告訴我打開哪個網址。我要送一則測試留言,然後重新整理頁面,確認留言還在(代表真的有存進資料庫)。怎麼算過:送出留言後,重新整理頁面,留言還在,就是真的存進 Supabase 了。你也可以回 Supabase 的 Table Editor 看
guestbook 表,那筆留言就在裡面。如果重整就消失,代表沒接好,把畫面截圖貼給 Claude 說「留言沒存進去」。想多確認一次金鑰跟 RLS:可以請 Claude 寫一支小腳本,用 publishable key 試著新增、讀取、刪除各一次。我在本機的 Supabase 跑出來是這樣,新增跟讀取成功,刪除被 RLS 擋下來:
第 6 步推上 GitHub、部署到 Vercel,再補設環境變數(3 個 prompt)
本機會動了,把它推上 GitHub、部署到 Vercel。這裡有一個基礎版沒有的關鍵步驟:要在 Vercel 再設一次環境變數。
Prompt 8 推上 GitHub
幫我把這個專案上傳到 GitHub,repo 名字叫 my-guestbook。上傳前再幫我確認一次 .env.local 沒有被包進去。Claude 會做:初始化 git、建 repo、push。因為
.env.local 在 .gitignore 裡,金鑰不會被上傳,你可以去 GitHub 看,找不到 .env.local 就對了。Prompt 9 部署到 Vercel
把 GitHub 上的 my-guestbook 連到 Vercel 部署,完成給我網址。Claude 會做:連接 Vercel、部署,給你一個
xxx.vercel.app 網址。但這時候打開可能會壞掉或留言失敗,因為金鑰沒上傳,雲端還不知道你的資料庫在哪。下一步補上。Prompt 10 在 Vercel 設環境變數
提醒我去 Vercel 設環境變數。我要在 Vercel 專案的 Settings → Environment Variables 加上 SUPABASE_URL 跟 SUPABASE_PUBLISHABLE_KEY,值跟我本機 .env.local 一樣,環境選 Production,設完要重新部署。你要做:到 Vercel 專案 → Settings → Environment Variables,把那兩個變數名稱跟值貼進去(選 Production),按 Save。
.env.local 不會上傳,所以雲端這邊要再貼一次。名稱要跟本機一字不差。(示意圖)為什麼要設兩次?本機的
.env.local 故意不上傳(金鑰才安全),所以雲端的 Vercel 拿不到。你得在 Vercel 後台「重新告訴它一次」。Vercel 官方文件也寫明,改了環境變數只對新的部署生效。所以最常見的狀況是本機會動、上線就壞,原因多半是環境變數沒設到 Vercel,或設完忘了重新部署。Prompt 11 重新部署 + 線上驗證
環境變數設好了,幫我重新部署一次,然後打開線上網址,我要送一則留言確認線上版本真的能存進資料庫。怎麼算過:重新部署後打開線上網址,送一則留言、重新整理還在,就大功告成。你的網頁現在是「活的」了,任何人從任何裝置留言都會存進你的雲端資料庫。
這篇順便幫你避開的資安雷
一旦網頁有了後端跟資料庫,就開始碰到「資安」。AI 寫程式很會「能跑」,但常常「能跑但不安全」。這篇的做法已經幫你內建了三個正確習慣:
金鑰不進版控
金鑰只放
.env.local、被 .gitignore 排除,永遠不會出現在 GitHub。程式碼裡只用 process.env 讀名字。資料庫預設鎖死,再開最小權限
RLS 先全鎖,再只開「讀 + 新增」,不開刪除跟修改。別人改不了、刪不掉你的資料。
機密金鑰留在後端
碰資料庫的程式只跑在伺服器端,金鑰不會被送進訪客的瀏覽器。真正的超級金鑰 secret key(舊制叫
service_role)會繞過所有 RLS,這篇完全沒用到,也絕對不該放前端。延伸閱讀:什麼能讓 AI 直接寫、什麼必須自己盯,我整理在 Vibe Coding 是什麼?那篇。越往會員、金流走,越不能純靠「跟 AI 聊一聊」。
本機正常、線上壞掉、留言存不進去的處理方法
有後端之後,卡關的點跟基礎版不太一樣,最常見這幾種:
- 本機會動、線上壞掉:多半是 Vercel 沒設環境變數,或設完忘了重新部署。回第 6 步的 Prompt 10。
- 留言送出沒反應 / 存不進去:先看錯誤訊息。出現
permission denied或42501是少了 grant;沒有錯誤但存不進去,多半是 RLS 開了卻沒加 insert 政策(整張表鎖死)。把錯誤訊息貼給 Claude 說「留言寫不進去,幫我看 grant 跟 RLS 政策」。 - 出現 Invalid API key:確認你貼的是
sb_publishable_開頭的那串、前後沒有多複製到空白,而且本機跟 Vercel 的變數名稱一樣是SUPABASE_PUBLISHABLE_KEY。 - Terminal 跑出紅字:直接整段複製貼給 Claude,跟它說「我卡在這裡」。
- 不確定金鑰有沒有外洩:問 Claude「幫我確認我的金鑰沒有被寫死在程式碼、也沒有被推上 GitHub」。
通用急救 prompt:
這是我看到的畫面:
[把你看到的畫面 / 錯誤訊息貼在這裡]
我本機是正常的,線上 / 這一步出問題。
幫我看怎麼解,一步一步帶我。
不想自己來
需要有資料庫 / 後台 / 會員的網頁?
留言板、報名表單、會員系統、後台收單,這種「有後端」的網頁比一頁式複雜,規格、資安都要把關。先聊聊你想做什麼,我幫你評估怎麼做最合適。
免費諮詢 →常見問題
Q:這篇跟基礎版差在哪?
基礎版做的是一頁式靜態網頁,只有文字圖片按鈕、沒有資料庫。這篇多了後端 API、資料庫、環境變數三樣,做出來的留言板別人留的話會永久存著,這是靜態網頁做不到的。
Q:要先會寫程式嗎?
不用,一樣跟 Claude 講中文。但建議先做過基礎版、熟悉 Claude Code / GitHub / Vercel 流程再來,這篇步驟比較多,先有手感會順很多。
Q:Supabase 要錢嗎?
免費方案就夠做留言板跟個人專案,每個專案有 500 MB 的資料庫空間。要注意兩條規則:免費方案最多同時開 2 個專案,專案連續一週沒人用會被暫停。用量很大(商業產品)才需要升級。
Q:我照舊教學拿了 anon key,還能用嗎?
現在還能用,但 Supabase 官方說舊的 anon 和 service_role 會在 2026 年底停用。建議直接到 Project Settings → API Keys 建一把 publishable key,把本機
.env.local 跟 Vercel 的變數一起換掉,再重新部署。Q:環境變數是什麼?為什麼重要?
就是把金鑰、密碼這種機密從程式碼裡抽出來、單獨放在一個不會被上傳的檔案。重要是因為金鑰一旦推上 GitHub 被看到,等於把資料庫鑰匙公開。AI 寫程式最容易犯的錯之一就是把金鑰寫死在程式碼裡。
Q:可以接著做會員登入、收款嗎?
可以,這篇的後端 + 資料庫 + 環境變數就是登入、收款的地基,Supabase 也有內建會員登入。但越複雜的功能資安風險越高,會建議找人把關,不要純靠跟 AI 聊。
Q:手機可以跟著做嗎?
不行,跟基礎版一樣要桌面電腦(Mac / Windows)。手機跑不了 Claude Code 的指令列跟 npm / git / vercel。
這篇用到的工具
Claude Code(Anthropic 官方 CLI) claude.com/claude-code
Next.js(前後端框架,Vercel 出品) nextjs.org
GitHub(免費 code 託管) github.com
Vercel(免費網頁部署;免費的 Hobby 方案限個人、非商業用途) vercel.com