大家在開發雙邊市場(Two-Sided Marketplace)產品時,常常會面臨「如何同時滿足 C 端消費者與 B 端商家」的產品難題,而在工程上,如何維持程式碼品質並高效推進專案,更是一大挑戰。
這次想與大家分享我獨立開發的台灣美甲情報社交 App —— Nailora。這款專案歷經約 300 個 commits,不僅成功建構出連接消費者(找靈感、預約、評價)與店家(展示、管理預約)的雙邊平台,更在過程中沉澱出了一套嚴格的工程紀律,以及「利用 Claude Code 開發大型專案」的 AI 協作方法論。
作為 Nailora 產品家族的核心,本專案也衍生出了 NailNote 本地美甲筆記 App 複盤 與 NailPost 自動發文工作流複盤。以下將針對技術棧、關鍵工程決策、AI 開發心法以及產品策略進行深度複盤。
現代化技術棧與架構概觀
為了快速驗證想法並保持優異的效能,Nailora 在前後端技術的選擇上兼顧了開發效率與系統擴充性:
技術棧一覽
| 階層 | 採用的技術與套件 |
|---|---|
| 前端 | React Native 0.81 + Expo SDK 54 + Expo Router(檔案型路由)+ 嚴格 TypeScript(strict mode) |
| UI 表現 | FlashList(高效能清單)、@gorhom/bottom-sheet、expo-image、react-native-maps、reanimated |
| 狀態 / 資料流 | Supabase Auth + 自建 AuthContext + Mock 優先(lib/mock)後接真實 API |
| 後端 | Supabase(PostgreSQL + RLS policy + Edge Functions + Storage) |
| 認證 | Apple Sign In / Google OAuth / LINE 三種第三方登入 |
| 監控 | Sentry 錯誤追蹤 |
系統架構與業務邏輯
- App 端設計:規劃了五個主要 Tab(設計瀑布流、趨勢探索、用戶投稿、預約管理、個人中心),並搭配作品詳情、沙龍詳情、預約流程、即時訊息、美甲筆記等子頁面。
- 後端資料庫與權限:底層設計了數十張業務表(如
designs、shops、bookings、messages、reviews、albums等)。每張表皆配置了多條 Row Level Security (RLS) 政策,嚴格區分 anon(匿名)、authenticated(已登入)與 service_role(系統管理)三層權限。 - 複雜邏輯與圖片處理:針對建立預約、成員管理、標記已讀等複雜商業邏輯,統一走 RPC(遠端程序呼叫)處理。而圖片上傳則透過 Edge Function 在後台預先生成多種尺寸後,再存入 Supabase Storage,以最佳化行動端的載入速度。
- 資料來源:主要依靠用戶的主動投稿與店家的作品上傳,並提供 Instagram 連動功能(可依特定 hashtag 自動匯入),而非盲目爬取競品資料。
關鍵設計決策與工程經驗
在約 300 個 commits 的開發歷程中,我踩過不少坑,也提煉出了幾項關鍵的工程規範:
1. 堅持 Mock First 開發
在後端 Supabase 還沒完全建置好之前,先用假資料把 UI 與互動邏輯完整實作。但這裡有一個至關重要的原則:必須制定「一份資料一個 mock 陣列、禁止平行陣列」的單一真相源規則。如果前期圖方便使用了多個平行的 mock 陣列,後期切換成真實 API 時,程式碼將面臨全面重寫的慘劇。
2. 業務分類維度必須統一在同一個層級
在專案早期,我曾嘗試用多層的列舉(如 PlanType)來描述預約方式,結果造成了邏輯上的嚴重衝突。後來痛定思痛,將分類統一化簡為「店家層的 bookingMethod + 菜單層的 requiresConsultation」。
- 教訓:業務分類的維度如果疊加太多層,極易互相打架,設計時應盡量扁平與單一化。
3. 時區處理:一律使用 timestamptz
行動端在處理預約時段時,最容易因為使用者與伺服器的時區誤差導致時間錯位。我們採取「一律使用 timestamptz 並做 round-trip 雙向驗證」的策略。時區問題必須在規範層提前預防,而不是等 bug 出現後才疲於奔命地修改。
4. 登入失敗要追查真正的根源
在接入 Google 登入時,曾遇到「登入失敗」的表象。深入排查後發現,真正的根因並非 OAuth 設定錯誤,而是 callback 污染了 returnTo 參數(closure 產生的副作用)。
- 經驗:處理回調鏈時要格外小心副作用,且這類第三方登入流程,務必使用「實機測試」而非 Expo Go 模擬。
5. 大規模重構前,先畫出「影響面地圖」
當專案規模變大,一個核心呼叫鏈的變動動輒會牽連 20 個以上的檔案。如果沒有提前繪製出影響面導航圖,重構時就極易出現測試盲點,顧此失彼。
用 Claude Code 開發大型專案的實踐方法
這套「與 AI 協作開發大型專案」的方法論,是本專案最具有遷移價值的無形資產:
- 分層知識文件,而非單一 README:
我們捨棄了將所有事情塞進一個 README 的做法,改採分層結構:
- 執行層:透過
CLAUDE.md定義絕對不可踩踏的開發紅線。 - 決策層:記錄跨任務約束的決策歷史。當需要推翻舊決策時,使用「刪除線」保留歷史軌跡,絕不直接回溯改寫,以確保 AI 能理解脈絡。
- 規範層:建立
standards子資料夾,作為程式碼與架構的「單一真相源」。 - 歷史層:存放開發計劃(plans)與執行報告(reports)。
- 執行層:透過
- Agent 職責分離:
避免讓同一個 AI 角色包辦所有事。我們明確劃分職責:
planner:只負責分析與設計,絕不改動程式碼。evaluator:只負責依契約驗收,不著手修理 bug。researcher:只負責蒐集資料,不參與規劃。 角色權責清晰,能有效避免 AI 產生幻覺或寫出邏輯衝突的程式碼。
- 契約驅動驗收:
在開始每個開發任務前,先產出明確的「驗收契約」。任務完成後,讓
evaluator進行機械式的檢查(例如:強制執行tsc檢查、對照單一真相源規範),降低人為主觀判斷的失誤。 - 健康度指標監控:
定期追蹤
CLAUDE.md與技能(skills)的 token 大小,並監控決策索引與正文的同步程度。一旦文件過於膨脹,系統會自動發出提示,強迫進行知識瘦身。
雙邊市場的產品冷啟動策略
從產品策略的角度來看,雙邊市場最大的難題就是「雞生蛋、蛋生雞」的冷啟動窘境。Nailora 採用的通用打法如下:
- 先補供給端(店家),再拉需求端(消費者):沒有豐富的內容與美甲作品,消費者點進來也是一片空白。因此,前期重心放在開拓店家,先把作品內容「鋪起來」。
- 種子用戶從身邊關係開始:不急著在早期進行大規模的付費推廣,而是從身邊熟悉的美甲師與熱愛美甲的朋友開始試用。
- 為早期合作者提供強烈誘因:例如主動協助美甲師拍照、幫忙將他們既有的社群(如 IG)作品與資料搬遷至平台,將他們的加入門檻與摩擦力降到最低。
專案現況
目前 Nailora 的各個核心功能層(包含流暢的瀑布流瀏覽體驗、第三方認證、店家後台管理、用戶投稿、預約交易流程以及各項留存功能)已大致開發完畢,並且能夠在開發版實機上穩定運行。
為了簡化初期的交易複雜度,金流部分暫時採用「現場付款」的方式,目前整體進度屬於「功能完整、待啟動上架流程」的階段。
小結
Nailora 的開發不僅是一次技術上的實踐,更是一次將軟體工程紀律與 AI 協作發揮到極致的嘗試。透過 Mock First、嚴格的 TypeScript 規範,以及首創的 Claude Code 分層知識文件管理,我們證明了即便是獨立開發者,也能有條不紊地駕馭高複雜度的雙邊市場專案。
如果你對此類專案的架構演進或 AI 輔助開發有興趣,歡迎參考以下相關的複盤筆記,了解更多延伸應用:
- 專案複盤-MOC
- NailNote 本地美甲筆記 App 複盤 — 專注於純本地端應用的極簡版拆解
- NailPost 自動發文工作流複盤 — 探討如何透過自動化工作流進行品牌行銷
- AI-LLM-MOC — 深入了解背後共通的工程與 AI 協作概念