HatchedDocs
Concepts

Streaks

Consistent-daily-activity counters that reward habit, not volume.

A streak is a counter that ticks once per UTC day when a given event fires. If the user skips a day, the counter burns. At configured milestones, a streak awards bonus coins, tokens, or badges.

Why streaks exist

Coins reward each action; streaks reward showing up. A well-placed streak is often the single biggest retention lever in a gamification economy.

How they work

  • Bound to one event type (the "today's activity" signal).
  • One tick per UTC day maximum.
  • Hatched fires streak.milestone webhooks at [7, 14, 30, 60, 90, 180, 365] by default (configurable).
  • Missing a day resets to zero unless a grace token is available.

Example

daily_lesson streak — +5 coins every tick day, +50 bonus at 7 days, +200 + 1 premium token at 30 days. Awards a "Week Warrior" badge at 7 days that shows off in the widget.

How to set it up

  1. Pick the event type that counts as "today's activity".
  2. Set a per-day bonus (optional).
  3. Add milestone bonuses for the thresholds that matter to you.
  4. Copy the streak key from Dashboard → Streaks.
  5. Pick a display mode — count, row, or mini (a bare inline 🔥 N chip for navbars and menus).
  6. Mount the streak widget with data-streak-key="…" (and optionally data-display-mode="mini").

The streak key is the stable workspace-level identifier for one streak definition, such as daily_lesson. It is not generated by the widget and it does not come from the user's buddy state. Treat it like app configuration: hardcode it in a shared constant, store it in an environment variable such as NEXT_PUBLIC_HATCHED_STREAK_KEY, or pass different keys to different streak mounts when you intentionally show multiple counters.

Gotchas

  • Streaks tick in UTC. Multi-timezone products may see users "burn" during their night. If this matters, model your own tick event instead of using a daily_login heuristic.
  • No grace days are built in — if you need them, grant a freeze token the user can burn.