Plan capabilities
Which Hatched widgets, capabilities, and quotas land on which subscription tier. Auto-generated from packages/shared/src/pricing.ts.
This page is auto-generated from packages/shared/src/pricing.ts. The same
constant drives the backend PlanGuard, the pricing page, and dashboard
upgrade banners — so every gate you see in product is encoded below.
Plan keys (starter, growth, pro, enterprise) map to public names
Design Sandbox, Launch, Optimize, Govern. Backend guards always use the keys.
Widget × Plan
Which data-hatched-mount="…" values render successfully on each plan. A
gated widget mount still loads but the API will return 403 plan_feature_locked
(with details.required_plan and details.upgrade_url) until the customer
upgrades. If the plan covers the feature but an operator has turned it off in
Settings, the API instead returns 403 capability_disabled.
| Widget | Design Sandbox (free) | Launch ($149/mo) | Optimize ($499/mo) | Govern (custom) | Capability flag |
|---|---|---|---|---|---|
buddy | ✓ | ✓ | ✓ | ✓ | always available |
marketplace | — | ✓ | ✓ | ✓ | marketplace |
leaderboard | ✓ | ✓ | ✓ | ✓ | always available |
badges | ✓ | ✓ | ✓ | ✓ | badges |
streak | ✓ | ✓ | ✓ | ✓ | streaks |
path | — | — | ✓ | ✓ | paths |
tokens | ✓ | ✓ | ✓ | ✓ | tokens |
kudos | ✓ | ✓ | ✓ | ✓ | kudos |
group-quest | — | ✓ | ✓ | ✓ | group_quest |
feed | ✓ | ✓ | ✓ | ✓ | seesaw_bump |
mystery-box | — | ✓ | ✓ | ✓ | mystery_box |
league | — | ✓ | ✓ | ✓ | leagues |
council | — | — | — | ✓ | council |
hexad-survey | ✓ | ✓ | ✓ | ✓ | always available |
A widget marked always available has no capability flag — every tier
can mount it. leaderboard and feed-style surfaces fall here because
they read data the platform always produces.
Capability × Plan
Raw PlanFeatures matrix. Backend @RequiresCapability('foo') decorators
gate on these keys; the dashboard reads the same map to render locked-state
banners. New capabilities must be added to PlanFeatures in pricing.ts
before they can be referenced anywhere.
| Capability | Design Sandbox (free) | Launch ($149/mo) | Optimize ($499/mo) | Govern (custom) |
|---|---|---|---|---|
advanced_analytics | — | — | ✓ | ✓ |
badges | ✓ | ✓ | ✓ | ✓ |
boosters | — | ✓ | ✓ | ✓ |
cause_counter | ✓ | ✓ | ✓ | ✓ |
council | — | — | — | ✓ |
evolution | — | ✓ | ✓ | ✓ |
evolution_generative | — | ✓ | ✓ | ✓ |
founding_cohort | — | — | ✓ | ✓ |
gamification_planner | ✓ | ✓ | ✓ | ✓ |
generative_media | — | ✓ | ✓ | ✓ |
group_quest | — | ✓ | ✓ | ✓ |
hosted_surface | — | — | ✓ | ✓ |
kudos | ✓ | ✓ | ✓ | ✓ |
leagues | — | ✓ | ✓ | ✓ |
lottery | — | ✓ | ✓ | ✓ |
marketplace | — | ✓ | ✓ | ✓ |
mentorship | — | — | ✓ | ✓ |
multi_audience | — | — | ✓ | ✓ |
mystery_box | — | ✓ | ✓ | ✓ |
paths | — | — | ✓ | ✓ |
profile_pages | — | — | ✓ | ✓ |
profile_pages_v2 | — | ✓ | ✓ | ✓ |
seesaw_bump | ✓ | ✓ | ✓ | ✓ |
showroom | — | — | ✓ | ✓ |
streaks | ✓ | ✓ | ✓ | ✓ |
teams | ✓ | ✓ | ✓ | ✓ |
tokens | ✓ | ✓ | ✓ | ✓ |
wardrobe | ✓ | ✓ | ✓ | ✓ |
Quotas + support
| Plan | Events / month | Audiences | Welcome credits | Monthly credit grant | Support |
|---|---|---|---|---|---|
| Design Sandbox (free) | 10,000 | 1 | 20 | 0 | community |
| Launch ($149/mo) | 500,000 | 1 | 0 | 50 | standard |
| Optimize ($499/mo) | 5,000,000 | 3 | 0 | 250 | priority |
| Govern (custom) | Unlimited | Unlimited | 0 | Unlimited | sla |
Event quota counts inbound POST /events calls. Once a tenant hits the
monthly cap the API returns 402 event_quota_exceeded carrying the reset
window (details.reset_at, the first of the next UTC month) and an upgrade
link. It is not a 429 — do not retry with backoff; back off until the
reset or upgrade the plan. SDK consumers catch this as
EventQuotaExceededError — see Error handling.
When you change pricing
- Edit
packages/shared/src/pricing.ts—PLAN_MATRIX. - Run
pnpm --filter @hatched/docs generate:plan-matrixto regenerate this page. - Commit both files in the same PR.
generate-plan-matrix.ts --checkis part of CI so drift fails the build.