给业余网球玩家的社交 + 比赛记录 app —— 找到搭子、约起来、把比分记下来、攒出自己的赛季。 现在已经上线,真实球友在真实球场用起来了。
我的本职是供应链计划员 —— 天天打交道的是表格和采购单,不是代码。 React 我写不来,也不装会。但我打网球,而且和所有球友撞上同一堵墙: 约球散落在各个群里,比分只活在脑子里。这个项目,就是 AI 时代一个代码小白 把这个痒处当真之后发生的事 —— 产品自己设计,施工交给 AI,最后 ship 给真实朋友用。 四步,不掺水地讲。
每次约球都散在群聊里,每个比分都只在我脑子里。我想要一个地方,既能找到搭子,又能把历史记下来 —— 首先为自己做,不是为市场做。
一行代码都还没有的时候,先把整个产品画完:34 个画板、每个页面每种状态,外加一份带验收标准的交付规格。真正的功夫,是决定不做什么。
React 和 SQL 是 Claude 写的;周边每个决定是我做的 —— 下一步 ship 什么、一个页面该是什么手感、哪个取舍赢。每次生产数据变更,依然由我亲手审、亲手执行。
不是 demo:朋友们注册进来,反馈几天内改写了路线图,产品在一个周六早上的球场上证明了自己。Ship 出去,胜过完美。
业余网球玩家最常撞上的两堵墙:"今天没人陪我打" 和 "我上次跟谁打的什么比分?" Tennis Buddy 把"发现搭子"和"记录比赛"做进同一条闭环 —— 现在还加上了社交层,让每场比分都有地方聊。
定向邀请,或谁都能加入的 open game。接受/婉拒、赛前聊天、一键加进手机日历 —— 打完按盘录入比分,胜负自动判定,比赛沉淀进历史记录。
奥克兰东区五家真实俱乐部、真实球场数,按 NTRP 等级筛球友,看附近的 open game。访客不注册也能直接浏览真实首页。
真实的社区 feed:发帖可附上战绩卡,评论、点赞、关注,球员主页有赛季数据和交手记录(H2H)。这是 Phase 3,已上线生产环境,不是效果图。
5 月上线的第一版是砍过的简化版。7 月我决定回到最初的 34 画板完整设计, 按 phase 一段段重建 —— 每一步都直接发上生产环境,真实朋友一边施工一边注册进来。
回到最初的设计:五个 phase 的施工计划,一条规则 —— 约球主循环跑通就上线,不等完整路线图。
Phase 1–2 进生产:数据层地基 + 完整比赛生命周期 —— 邀请、open game、赛前聊天、日历文件、按盘记分。
朋友们注册进来,mock 数据当晚退役。加上三步引导向导,首页对访客开放 —— 不注册也能逛。
App 搬到 tennis.gimbo.co.nz,事务邮件走自己的子域名 —— 登录链接从每小时 2 封提到 30 封,直落收件箱不进垃圾箱。
群里发了一条:当晚 +4 注册,登录链接零流失,还有人填了我从没列过的主场俱乐部。访客分析上线。
Phase 3 社交 feed 当天上线,邀请邮件也开始直接从数据库里发出。而真正重要的里程碑:朋友发来邀请 → 接受 → 赛前聊天 → 周六早上真的站上球场 → 比分录进 app。
前端 React 19 + Vite + MUI v6,设计语言取自法网(Roland-Garros)的色调和字体, 用 Material 3 的形状语言落地。Supabase 负责数据、登录、安全 —— 连邮件都从 Postgres 里直接发。 Vercel 上 push 即部署,没有需要照看的服务器。
一个人端到端 —— 设计、前端、后端、部署,加上真实用户的运营。 下面每一项都在生产环境上跑着,不在路线图里。
数据层地基、完整约球主循环、社交层都已经在生产环境。剩下发现层和通知层 —— 不过邀请邮件已经提前插队上线了。
建表、行级安全、引导流程、公开首页、社交图谱、库内邀请邮件 —— 每一次生产数据变更都人工审过、亲手执行。
是朋友,不是测试账号 —— 通过 magic link 注册,填的是真实资料和真实主场,包括我从没列进去的俱乐部。
一场比赛从邀请 → 接受 → 聊天 → 球场 → 录分,全程跑在产品里。这是最重要的那个数字。
过程比结果有意思 —— 用一周晚上把真产品交到真人手里,这几个想法我会一直带着。
Phase 1–2 上线时,社交层和发现层都还不存在。真实用户在施工中途就进来了 —— 他们的反馈几天内就改写了下一个 phase 该做什么。
定向邀请、open game、待确认、已完赛,全住在同一张 matches 表里。更少的 join、更少的同步 bug,整条闭环只有一个 source of truth。
规则住在 Postgres 里:访客能浏览真实 open game,但 email 列永远被 revoke。前端就算被绕过,数据库这堵墙也不放行。
过期没约满的 open game 只有发起人自己能看见 —— 那就让发起人下次打开 app 时顺手清掉。全覆盖、零定时任务、零新基建。
注册流程从没问过用户叫什么 —— 真人进来第一天就暴露。比分存反了,提交者自己看是对的,只有对手那侧才能看出来。
共享 SMTP 每小时只发 2 封登录邮件 —— 同一小时注册的第三个朋友永远进不来。自有发信域名解决了任何代码都解决不了的增长问题。
Tennis Buddy 已经上线。任意邮箱登录,magic link 几秒到 —— 或者不注册,先逛逛现在开着的 open game。
打开 Tennis Buddy →永不存储密码,登录只用邮箱 magic link(Supabase Auth)。 你的邮箱只用于发送登录链接和你主动请求的比赛邀请。