
想做指甲的人翻遍社群也拼不出「哪一家做得出這個款、什麼時候有空」,美甲師則得在私訊裡一則一則手動排班,兩邊都很辛苦,卻沒有一個地方把他們接起來。
Nailora 是一個同時服務「找美甲的人」與「開店的人」的 App,這篇也整理了一套跟 AI 協作開發大型專案的做法。
兩邊同時被滿足,這個市場才成立
App 分成兩側:給顧客的瀏覽、投稿、預約,給店家的管理、接單。任何一側沒做好,另一側就沒有理由留下來。
技術細節:雙邊市場的資料骨架
C 端五個主 Tab(設計瀑布流、趨勢、投稿、預約、個人),加上作品詳情、沙龍詳情等子頁。後端數十張業務表(designs、shops、bookings、messages、reviews 等),每張表配多條 Supabase RLS policy,區分 anon / authenticated / service_role 三層權限;複雜邏輯走 Edge Function,包含圖片上傳時預生成多種尺寸。
先立規矩,後面才不用補課
開頭就定死三條:不准用「隨便型別」,介面先用假資料再接真資料,每張資料表都設好誰能看、誰能改。
技術細節:紀律清單
TypeScript strict mode、禁用 any;Mock First 開發(lib/mock);Supabase RLS policy 逐表設定;React Native 0.81 + Expo SDK 54 + Expo Router。
假資料要守一份資料一個真相源
同一筆資料拆成兩份假陣列給不同畫面用,接真資料庫時兩邊對不起來,得全部重寫。一份資料只能有一個假陣列。
分類疊太多層,系統會自己打架
用好幾層的類型欄位描述「這家店怎麼接預約」,不同層的設定會互相矛盾。店家層只管怎麼約,菜單層只管要不要先諮詢。
技術細節:欄位重構
多層 enum(PlanType)描述預約方式的寫法已移除,統一成店家層 bookingMethod 加菜單層 requiresConsultation。
時區問題要寫進規範先擋掉
今天在台北訂的下午三點,換一台手機卻顯示成別的時間。規範裡直接寫死:時間一律用帶時區的格式存,並驗證讀寫一致。
技術細節:時區處理
統一使用 timestamptz 型別,並在關鍵路徑做 round-trip 驗證。
排查要查到底層,別停在表面症狀
Google 登入一直失敗,症狀指向登入設定,根因是另一段回呼程式碼汙染了「登入後跳回哪裡」這個變數。這種副作用只有真機測得出來。
技術細節:closure 副作用
callback 汙染了 returnTo 變數,屬於 closure 副作用,與 OAuth 設定無關。須用實機而非 Expo Go 測試。
重構前先畫出這個改動會牽動誰
核心呼叫鏈動輒牽連二十幾個檔案。動大手術前先把影響範圍畫出來,不然會漏測某個角落。
最能帶走的是那套 AI 協作開發方法
四件事:文件依用途分層、AI 角色各管一段互不越界、任務先寫好怎麼驗收再讓 AI 做、盯著文件不要膨脹到失控。各自寫成獨立的筆記:
雙邊市場先養供給那一邊
雞生蛋的問題沒辦法兩邊一起拉。店家先把作品鋪好,消費者才有理由打開 App。第一批店家找身邊認識的美甲師,用幫忙拍照、搬社群內容把門檻降到最低。
現況能在實機上跑,並長出兩個分支
App 各功能層大致做完,金流先用現場付款,預計近期上線。這個題目長出兩個分支:離線筆記工具,以及幫品牌帳號產出貼文的流水線。
graph TD A[找美甲的人] --> C[Nailora 本體] B[開店的美甲師] --> C C --> D[拆出離線筆記工具,只留在自己手機裡] C --> E[品牌帳號的自動發文流水線,機器產、人按核准]
AI 產草稿,人按核准鍵
品牌帳號要固定發文,每週找題材、寫文案、做圖、排時間,很花時間。流水線自動掃趨勢、寫文案配圖、排版,寄信給我審核,按下核准才在隔天發出。哪一則貼文能代表品牌說話,決定權留在人手上。
相關
- NailNote 本地美甲筆記 App 複盤 — 拆出的純本地版
- AI-LLM-MOC — 共通的工程與 AI 概念