
從零到上線:用 Next.js 與 Supabase 重做個人官網的這一年
2026年2月9日 · waiting7777 · 4 分鐘閱讀
Life** 一個前端工程師在 2026 年如何把「架部落格」當成 side project,順便練熟 Auth、RLS 與部署。
我從來沒想過,重做一個個人官網會花掉這麼多個週末。但回頭看,與其說是「做一個網站」,不如說是逼自己把「前端、後端、權限、部署」在一條龍裡走完。這篇文章是那條龍的流水帳,以及我踩過的坑和學到的事。
為什麼要重做?
舊站是靜態部落格,沒有登入、沒有留言、沒有「我的收藏」。2025 年底我決定轉型做 AI Agent 與數據產品,個人品牌也需要一個能展示「會做全端、會管權限、會上線」的據點。所以目標很明確:一個可以寫文章、可以讓訪客登入留言與收藏、後台只有我能改的部落格。技術選型上,我選了 Next.js(App Router)、Tailwind、Supabase。理由很務實:Next 生態熟、Tailwind 出稿快、Supabase 把 Auth 和 Postgres 包在一起,不用自己架後端。
架構:前端、Auth、資料庫怎麼分工
整體是這樣分的:
- Next.js:前後端都在同一個 repo,頁面用 Server Components 拉資料,表單用 Server Actions 寫入。
- Supabase:負責使用者帳號(Email/密碼)、session(cookie),以及 Postgres 裡的
profiles、posts、comments、favorites。權限全部用 RLS(Row Level Security)管,前端只帶 anon key,不碰 service role key。 - Tailwind:從品牌色、字體到 dark mode 都寫在 CSS 變數和 utility 裡,沒有再包一層 design system。
Auth flow 是標準的「註冊 → trigger 建 profile → 登入後 cookie 帶 session,middleware 負責 refresh」。後台(新增/編輯文章)只給 profiles.role = 'admin' 的人進,這個檢查放在 layout 的 server 端,不是只藏前端按鈕而已。
幾個關鍵決定(以及為什麼這樣做)
1. 文章「發布/草稿」用 published_at 一個欄位搞定
不另外做 status 欄位。published_at 有值就當已發布,null 就是草稿。列表只查 published_at <= now(),後台查全部。這樣 RLS 和查詢都簡單,也少一個欄位要維護。
2. Slug 唯一、預填從標題來
每篇文章一個 slug,後台表單有「從標題產生」按鈕,用自訂的 slugify() 轉成網址用字串。寫入前再正規化一次,衝突就回傳「此 slug 已被使用」。沒有做自動加數字後綴,因為我希望網址可預測、好分享。
3. 封面圖與內文圖
封面圖用一個 URL 欄位 cover_image_url,後台填連結就好(之後要接 Supabase Storage 上傳再擴充)。內文用 Markdown,圖片寫 ,前端用 react-markdown 渲染,img 套好樣式即可。先求有再求好。
4. 留言與收藏「僅登入可用」
RLS 設定成:comments / favorites 只有 auth.role() = 'authenticated' 能讀寫,且每人只能改自己的。前端在文章頁用一個小區塊「登入後才能留言與收藏」,未登入就顯示登入連結,不暴露表單。
上 GCP 前我做了什麼資安自檢
要丟上 GCP 前,我列了一張清單,避免自己漏掉基本項:
- 環境變數:
NEXT_PUBLIC_*只放 Supabase URL 和 anon key;service role key、Resend API key 只存在 server 端,絕不進 client。 - 登入後導向:redirect 參數只接受
startsWith("/"),避免被導到外站。 - 後台:進 admin 前用 server 端檢查
profiles.role === 'admin',不信任前端隱藏按鈕。 - Markdown:用 ReactMarkdown 渲染,沒有
dangerouslySetInnerHTML;若以後支援 HTML,會加 sanitize。 - 部署:HTTPS、env 用 GCP Secret Manager 或環境變數注入,不把
.env打進 image。
這份清單我放在 repo 的 docs/SECURITY.md,之後每次要上線前都會再對一次。
若重來一次我會先做什麼不同
- 圖片上傳:一開始就規劃 Supabase Storage + 後台上傳,比「先只填 URL」少一次重構。
- Rate limit:登入、註冊、聯絡表單應該從第一天就加(Nginx 或 GCP 層),避免被亂打。
- E2E:關鍵 flow(註冊 → 登入 → 看文章 → 後台發文)至少用 Playwright 跑一輪,部署前會安心很多。
小結
這個 side project 的目標從來不是「做出最厲害的部落格」,而是用一個真實產品把 Next、Supabase、RLS、部署串起來。寫完這篇時,站已經能註冊登入、能發文、能顯示封面與內文圖、能區分草稿與發布,並且有一份自己會遵守的資安檢查表。如果你也在考慮用 Next + Supabase 做個人站或小產品,希望這篇流水帳能幫你少繞一點路。
下一步我會把圖片上傳接好、把留言區與收藏按鈕做完,然後真的寫幾篇技術文放上去。到時再來分享「從第一篇文到第一萬個訪客」的下一段故事。
— Waiting7777 / BridgeCraft,2026
訂閱電子報
AI Agent、前端開發、技術深度文章 — 有新內容時直接寄到你的信箱。