FlareStarter 文档
功能与集成

增长:推荐、折扣码、生命周期邮件

Referral 双边奖励、Stripe Promotion Codes 深链折扣、D0/D3/D7 生命周期邮件。

三个各自独立、可单独关停的增长切片:referral(推荐有礼)、promo(折扣码)、 drip(生命周期邮件)。共同的设计取向:幂等优先——每一次发奖、每一封邮件都经过 唯一约束或 ref 去重,重放、重试、多触发点并发都不会重复发放。

Referral:两档双边 credits 奖励

每位用户在 /app/referrals 有一个专属推荐码,分享链接形如 /r/<code>。

归因(首触,30 天):/r/$code 落地时种下 ref cookie 并 302 到注册页(无效码 也照常跳转,不给探测面)。注册成功后,better-auth 的 user.create.after databaseHook 读 cookie 落库归因——首触优先(referred_user_id 唯一约束,后来的码插不进去), 自我推荐直接拒绝。

两档奖励,双边发放(金额在 referral.config.ts):

阶段触发每侧奖励
verified被推荐人完成邮箱验证250 credits(即时正反馈)
paid被推荐人首次付费(个人 Pro 或组织的座位订阅/充值)1,000 credits(防刷主奖)

paid 蕴含 verified——直接付费的用户两档一起结。奖励通过 credits 的幂等流水入账,ref 形如 referral:{id}:{stage}:{side},所以结算函数 settleReferral 可以被任意触发点重复 调用:邮箱验证钩子、付费 webhook、加入组织钩子、每日 cron,每笔仍只发一次。

防刷上限:每个推荐人最多 50 个推荐计酬(按到达 verified 的数量计)。超限后停发的 只是推荐人侧,被推荐人自己的奖励照发——新用户不该为别人刷量买单。

credits 挂在组织上,而结算时对方可能还没有组织(例如刚注册未验证邮箱)。这种情况 settleReferral 直接跳过该侧,留给下一个触发点或每日 cron 的 settleRecent 补结(扫最近 90 天已达标的推荐,幂等重结,见 定时任务)。 事件驱动尽力而为,cron 兜底最终一致。

折扣码:Stripe Promotion Codes

码本身在 Stripe Dashboard 创建(coupon + promotion code),模板不重造那套 UI—— Stripe 是核销次数、有效期、启停状态的唯一事实源。模板补的是两件事:

  1. 所有 checkout 都收码:订阅、买断、充值的 Checkout Session 一律开 allow_promotion_codes,顾客在 Stripe 收银台手动输码。
  2. 深链自动应用:/pricing?code=XXX 会种 7 天的 fs_promo cookie,之后任何 checkout 创建时把 cookie 里的码解析成 promotion-code id、经 discounts 参数预先 应用——Stripe 收银台无法预填输码框,这是让分享链接"点开即生效"的唯一办法。 两个参数互斥:解析成功走 discounts,任何一环失败(无 cookie、格式不对、码已停用、 Stripe 抖动)都回退到手动输码入口,过期的活动链接永远不能挡住付款。

admin 后台有一个只读核销视图(码、折扣、已用次数、上限、过期时间)。只读是有意的: 写操作留在 Stripe Dashboard,避免两边状态互相踩。

Drip:D0/D3/D7 生命周期邮件

旅程在 drip.config.ts 里声明式定义,每晚由 cron 执行一批:

天数campaign发送条件
D0welcome无条件(欢迎邮件)
D3activate从未协作过——不属于任何 ≥2 人的组织
D7upgrade无任何活跃付费——没有座位订阅所在组织,也没有个人 Pro/买断

加一封新邮件 = 在配置数组加一项 + 按 邮件 的约定补模板与双语文案。

Claim-before-send:发送前先插入 (userId, campaign) 唯一行当锁,插入成功才发信。 进程在发送中途崩溃,最坏丢一封邮件,绝不双发——营销邮件宁漏勿重。发送失败只记 日志不回滚 claim,同一封不会反复重试。

合规:每封 drip 邮件带 HMAC-SHA256 签名的一键退订链接(/unsubscribe?uid=…&token=…), 无需登录即可退订(CAN-SPAM 要求非鉴权退出)。退订置 marketingOptOut,此后所有 campaign 跳过该用户;交易类邮件(验证、收据等)不受影响,也不带退订链接。

其余护栏:

  • 时效窗 14 天:campaign 只在 afterDays ≤ 用户注册天数 ≤ afterDays + 14 内可发。 错过即作废——日后改条件或切换模式,不会突然给一年前的老用户群发 onboarding 邮件。
  • 单次上限 100 封:保护 Resend 速率限制,积压的下一晚继续。
  • 没配 RESEND_API_KEY 就整体跳过:不能白插 claim 行把邮件静默烧掉。
  • solo 模式(见 单用户模式):D3 直接跳过(没有 邀请就没有"激活协作"可言);D7 只按个人套餐判定,文案与链接换用 solo 变体。

本地验证

  • Referral:登录拿到自己的码 → 无痕窗口走 /r/<code> 注册 → 在 pnpm dev 控制台 点验证链接 → 两侧 /app/credits 各出现一笔 250 credits 的 referral:* 流水。
  • 折扣码:Stripe 测试模式建一个 promotion code → 访问 /pricing?code=XXX → 发起任意 checkout,收银台已带折扣。
  • Drip:不用等 cron——选择/claim 路径在 workers 池测试里用假 sender 全覆盖, 照 drip.workers.test.ts 的写法调 runDrip 即可。

三个切片都遵循优雅降级:没配 Stripe 就没有折扣码,没配 Resend 就没有 drip, referral 页始终可用(奖励结算等到 credits 可用时补上)。

On this page