ENZH
和 AI 讨论这篇文章
ChatGPTClaude

盘盘猫开始算生意账了

📊 幻灯片

Day 20 到 Day 23 这四天基本都在赶里程碑,一共交付了三个正式的:积分经济、每日运势 Hub、PostHog 数据分析。四天下来合了 17 个 PR,166 次 commit。这几天转化、留存这些事想得比较多,感觉有点在算生意账的意思了。

盘盘猫冲过三个里程碑旗帜的马拉松赛道盘盘猫冲过三个里程碑旗帜的马拉松赛道

一个人也开始认真写 PR 了

这四天开始引入里程碑的做法:每个里程碑都是一个完整、可交付的增量,做完能明确说清楚之前和之后差在哪。同时也开始认真写 PR。

一个人给自己写 PR 图什么?对我来说主要是三件事:把当时的意图记录下来,留一条可追溯的变更历史,还有逼你自己想清楚这次到底要交付什么、为什么做。说白了核心就是最后那件,想清楚要交付什么,前两件算顺带的。

每个 PR 都带结构化描述:摘要、变更表格、带复选框的测试计划。当下写着是有点麻烦,但等三周之后想搞明白「当时为什么改这个」的时候,这些东西实打实有用。

M1 积分经济,100 个文件

M1 干的事情,是把「免费用」改成「免费试 + 付费用」。积分逻辑本身其实没什么技术含量,加加减减而已,这次真正费劲的全在边上的东西。

匿名用户怎么合并

新用户进来就是一个 Supabase 匿名账户,不用注册,能浏览、能用免费积分、能保存测算结果。等他哪天决定登录了,不管走 Google OAuth、邮箱还是兑换码,所有数据都得无缝合并过去:积分余额、测算记录、聊天历史、推荐关系,一样都不能丢。

匿名账户登录时,积分、记录、聊天历史、推荐关系整批无缝合并进登录账户,一样都不丢匿名账户登录时,积分、记录、聊天历史、推荐关系整批无缝合并进登录账户,一样都不丢

兑换码这条路本身就是个 state machine:idle → checking → redeeming/logging_in → success/errorRedeemCodeInput 组件自动格式化 PPM-XXXX-XXXX 的输入,处理完整生命周期。这里有个我觉得还挺巧的设计:匿名用户输了兑换码,后端直接把兑换码设成这个匿名账户的密码,码本身就是下次登录的凭证。

后来 PR #103 还修了一个 race condition:liunian 这个应用类型在 llm_costs_app_check 约束里漏掉了,生产环境 INSERT 直接失败。这种 bug 挺难受的,只在特定功能的特定路径上炸,平时完全看不出来。

跨标签页积分不同步

这个 bug 的路径是这样的:用户在一个标签页买了积分,切到另一个标签页,余额显示还是旧的。他以为购买失败了,又买一次,钱就花了两遍。

方案是 Supabase 实时订阅:每个标签页都监听积分变动,任何一个标签页扣了或者加了积分,其他标签页一秒内同步过来。听起来简单,但订阅的生命周期得做对:挂载时订阅,卸载时取消,标签页休眠之后还要重连。细节不少,或者说,坑基本都在生命周期上。

两个标签页各自订阅积分变动,一个标签页扣或加积分,另一个一秒内同步,避免误以为没买成而重复付款两个标签页各自订阅积分变动,一个标签页扣或加积分,另一个一秒内同步,避免误以为没买成而重复付款

7 种升级提示

UpgradePrompt 组件有 7 种触发类型,每种对应的用户状态不一样:

  • 测算中积分用完(紧迫感最高,购买意愿最强)
  • 每日运势浏览时余额不足(紧迫感低,先培养意识)
  • 测算完成后的满足时刻(情绪正面,适合追加销售)
  • 推荐提示(社交场景,「送礼」的框架)
  • 首次发现新功能(好奇心驱动,试用转付费)

提示有卡片和横幅两种样子,外加 24 小时的关闭冷却期,用户关掉了就一天之内别再弹,不然会觉得被骚扰。

M2 每日运势 Hub,又是 100 个文件

算命这个品类天然是事件驱动的:用户带着问题来,拿到答案就走了。每日运势 Hub 要解决的就是留存,给用户一个每天回来的理由。Hub 里放了五张卡片:八字日柱运势、星座运势、每日塔罗牌、黄历、占卜引导,每张卡都有自己的 CSS 主题。

内容全部预生成

这里有个关键决策:内容不是用户打开的时候现算的,是北京时间午夜的 cron 任务提前生成好的,用户打开直接读现成的。/api/cron/daily-content 这个 endpoint 用 Gemini 生成八字和星座运势,存进 daily_content 表,7 天前的数据自动清掉。cron endpoint 的密钥比较用了常量时间 XOR,这是安全审计提出来的,再加基于 IP 的 rate limit(30 次/分钟),时区统一按 Asia/Shanghai 处理。

这样用户早上 8 点打开 Hub,内容已经在那了,不转圈,直接出。感觉用户对「这产品靠不靠谱」的判断,很多就是从这种秒开还是转 3 秒的地方来的。

午夜 cron 提前把内容生成好存下,用户早上打开直接读现成的,秒开不转圈,而不是打开时现算等三秒午夜 cron 提前把内容生成好存下,用户早上打开直接读现成的,秒开不转圈,而不是打开时现算等三秒

占星模块顺手重构了

同一个 PR 里还把占星模块的国际化重构了:347 行的三语字典(zh-CN/zh-TW/en),行星、星座、相位、宫位都在里面,外加 70 多个结果页面的字符串。星盘轮盘重新画了一版,金色配暗色的主题,带度数刻度线、中文的行星和星座标签、交互式提示框。星盘计算和布局函数写了 78 个测试盖住。

合盘持久化

新加了 synastry_readings 表:出生信息加密存储,保存、加载、聊天整条流程都通了,历史记录 API 也接上了。加密这块没得商量,合盘测算里装的是两个人的出生信息。

M3 接 PostHog,11 个文件

M3 是接 PostHog:兑换码的事件追踪用 after() 做,不阻塞兑换响应,顺手清掉了被管理后台取代的旧管理路由。三个里程碑里这个规模最小,但作用不小。之前用户在产品里干什么,全靠猜;接上之后能看到了,反馈环路算是闭上了。

转化、留存这些事

这四天想得比较多的是转化漏斗、留存钩子、日活参与、推荐激励这些东西。这些是生意问题,但反正最后都是要用代码去解的:转化对应的是那 7 种升级提示,留存靠每日运势 Hub——还是那句话,给用户一个每天回来的理由——PostHog 负责把这些变成能看的数字。留存这件事,这次算是第一次认真想了一遍。功能清单还在那,慢慢排。

和 AI 讨论这篇文章
ChatGPTClaude

订阅更新

新文章发布时发到你的邮箱,不发别的。


© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0