大家在開發雙邊市場(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(設計瀑布流、趨勢探索、用戶投稿、預約管理、個人中心),並搭配作品詳情、沙龍詳情、預約流程、即時訊息、美甲筆記等子頁面。
  • 後端資料庫與權限:底層設計了數十張業務表(如 designsshopsbookingsmessagesreviewsalbums 等)。每張表皆配置了多條 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 協作開發大型專案」的方法論,是本專案最具有遷移價值的無形資產:

  1. 分層知識文件,而非單一 README: 我們捨棄了將所有事情塞進一個 README 的做法,改採分層結構:
    • 執行層:透過 CLAUDE.md 定義絕對不可踩踏的開發紅線。
    • 決策層:記錄跨任務約束的決策歷史。當需要推翻舊決策時,使用「刪除線」保留歷史軌跡,絕不直接回溯改寫,以確保 AI 能理解脈絡。
    • 規範層:建立 standards 子資料夾,作為程式碼與架構的「單一真相源」。
    • 歷史層:存放開發計劃(plans)與執行報告(reports)。
  2. Agent 職責分離: 避免讓同一個 AI 角色包辦所有事。我們明確劃分職責:
    • planner:只負責分析與設計,絕不改動程式碼。
    • evaluator:只負責依契約驗收,不著手修理 bug。
    • researcher:只負責蒐集資料,不參與規劃。 角色權責清晰,能有效避免 AI 產生幻覺或寫出邏輯衝突的程式碼。
  3. 契約驅動驗收: 在開始每個開發任務前,先產出明確的「驗收契約」。任務完成後,讓 evaluator 進行機械式的檢查(例如:強制執行 tsc 檢查、對照單一真相源規範),降低人為主觀判斷的失誤。
  4. 健康度指標監控: 定期追蹤 CLAUDE.md 與技能(skills)的 token 大小,並監控決策索引與正文的同步程度。一旦文件過於膨脹,系統會自動發出提示,強迫進行知識瘦身。

雙邊市場的產品冷啟動策略

從產品策略的角度來看,雙邊市場最大的難題就是「雞生蛋、蛋生雞」的冷啟動窘境。Nailora 採用的通用打法如下:

  • 先補供給端(店家),再拉需求端(消費者):沒有豐富的內容與美甲作品,消費者點進來也是一片空白。因此,前期重心放在開拓店家,先把作品內容「鋪起來」。
  • 種子用戶從身邊關係開始:不急著在早期進行大規模的付費推廣,而是從身邊熟悉的美甲師與熱愛美甲的朋友開始試用。
  • 為早期合作者提供強烈誘因:例如主動協助美甲師拍照、幫忙將他們既有的社群(如 IG)作品與資料搬遷至平台,將他們的加入門檻與摩擦力降到最低。

專案現況

目前 Nailora 的各個核心功能層(包含流暢的瀑布流瀏覽體驗、第三方認證、店家後台管理、用戶投稿、預約交易流程以及各項留存功能)已大致開發完畢,並且能夠在開發版實機上穩定運行。

為了簡化初期的交易複雜度,金流部分暫時採用「現場付款」的方式,目前整體進度屬於「功能完整、待啟動上架流程」的階段。


小結

Nailora 的開發不僅是一次技術上的實踐,更是一次將軟體工程紀律與 AI 協作發揮到極致的嘗試。透過 Mock First、嚴格的 TypeScript 規範,以及首創的 Claude Code 分層知識文件管理,我們證明了即便是獨立開發者,也能有條不紊地駕馭高複雜度的雙邊市場專案。

如果你對此類專案的架構演進或 AI 輔助開發有興趣,歡迎參考以下相關的複盤筆記,了解更多延伸應用: