Side Projects
RoundQ 圈問

與好友圈深度對話的問答平台。在私密的好友圈中,每一期由發起人設計 3–10 個精心問題,好友一起回答;答案以「人」為中心完整呈現,而不是散落在群組訊息裡。支援 Tiptap 富文本與圖片、按讚留言、歷史回顧、公開圈與範例 Round、中英多語系。
要解決的問題
這個專案的起點是一份每月發給朋友的問卷:問大家最近在忙什麼、有什麼開心或煩惱的事,收到回覆後再手動整理成文件分享出去。群組聊天室雖然即時,但訊息很快被洗掉,事後也很難回顧;問卷則需要人工整理,而且很難同時經營好幾個朋友圈。RoundQ 想把「收集、整理、分享」這段流程自動化,同時保留聊天室沒有的結構與深度。
畫面截圖
主要功能
以期為單位的問答
發起人為好友圈設計一期 3–10 個問題,可以從分類好的問題模板挑選,也能為一期同時指定多個好友圈。每一期都會歸檔,之後隨時可以回頭翻看。
以人為中心的回答呈現
每位朋友對所有問題的回答被整理成一張完整的卡片,而不是依問題拆散。按讚與留言也是針對這整份回答,讓互動回到「這個人最近過得怎樣」。
富文本與圖片
回答使用 Tiptap 編輯器,可以圖文混排;圖片在瀏覽器端先壓縮再上傳到 Supabase Storage。
延遲揭曉
發起人可以選擇立即公開答案,或在達到指定回答人數、到達截止時間、由發起人手動操作時才揭曉,讓每個人先獨立思考再看別人的答案。發起人也能把個別問題設為只有自己看得到。
溫和的即時更新與通知
有人提交新回答時,頁面只顯示「有新回答,點擊查看」的提示,不會突然改變正在閱讀的內容。站內通知、瀏覽器推播與留言中的 @提及 會把朋友帶回來。
公開圈與範例 Round
除了私密圈,也支援公開圈與不需登入就能瀏覽的範例 Round,讓第一次來的人先看到實際的樣子。介面提供繁體中文與英文。
技術架構
前端使用 Next.js(App Router)、React 19、TypeScript strict mode 與 Tailwind CSS v4,元件以 shadcn/ui 為基礎,部署在 Vercel。後端選擇 Supabase,一次取得 PostgreSQL、Auth、Realtime 與 Storage,讓一人開發的專案不必自己維護伺服器。伺服器狀態交給 TanStack Query,UI 狀態用 Zustand,寫入操作透過 next-safe-action 包裝的 Server Actions,並以 Zod 驗證輸入。權限規則寫在資料庫的 Row Level Security policy 裡,前端只負責呈現;多語系使用 next-intl,測試則以 Vitest 與 Playwright 分別涵蓋單元與端對端流程。
技術挑戰與取捨
答案隱藏不能只靠前端
延遲揭曉的重點是答案公開前,其他成員真的拿不到資料。只在前端把答案藏起來,任何人看網路請求就能繞過。最後把規則寫進 responses 資料表的 RLS policy:自己的回答永遠看得到、發起人看得到全部、其他人要等該期揭曉後才查得到。依截止時間揭曉的部分由資料庫內的 pg_cron 每分鐘檢查,揭曉時再由 trigger 產生通知給已回答的成員。
一期問答跨多個好友圈
早期設計是一期只屬於一個圈子,但同一組問題常常想同時問大學同學和家人。改成多對多之後,新增 round_circles 關聯表,並在每筆回答記錄它來自哪個圈子。RLS 隨之調整為:發起人可以看到所有圈子的回答,一般成員只看得到同圈的回答。這樣一份問卷可以重複使用,不同圈子的回答也不會互相曝光。
成員離開後,回答要不要留下
這個問題影響資料表設計,所以在動工前先寫成決策文件。考慮過的選項有:保留回答、隨成員離開一起刪除、讓離開的人自己選。刪除會讓其他人的回應失去上下文,也違背「可以回顧」這個核心價值;讓使用者選擇則增加介面與實作的複雜度。最後採用保留回答:離開圈子只移除成員資格,過去的回答仍留在該期裡,其他成員回顧時對話依然完整。
現況
響應式網頁應用,已上線於 roundq.app,支援桌面與手機瀏覽器,介面提供繁體中文與英文。
使用技術
- Next.js 16
- React 19
- Supabase
- TanStack Query
- Zustand
- Tiptap
- Tailwind v4
- next-intl
