Usage dashboard
How three meters (training chars, messages, chatbots) are shown at `/app/usage`, with color bands at 75%, 90%, and 100%.
The usage page at /app/usage shows three meters against your plan's limits, with escalating urgency as you approach them.
Page header
- Eyebrow: USAGE
-
: How much of your plan you're using -
Subtitle: "{plan name} plan". When
usage.period_startandusage.period_endare both present, "· resets {period_end}" is appended.
Top-right link: See plans → → /app/billing.
Thresholds
Verified from level(used, max):
| Percent used | Level |
|---|---|
| 0 – 74% |
ok |
| 75 – 89% |
warning |
| 90 – 99% |
critical |
| 100% |
full |
The percent is computed as min(100, round(used / max * 100)).
Warning and critical banners
An UrgencyBanner is rendered above the meters, gated by the aggregated state:
-
If any meter is
criticalorfullAND a next tier exists: critical banner (destructive-toned). -
Else if any meter is
warningAND a next tier exists: warning banner (amber-toned).
Critical copy (verbatim)
- Heading: "You've hit one or more plan limits"
- Body: "Your chatbots will stop accepting new content, messages, or training until you upgrade."
- Button: Upgrade to {next-tier-name} (filled)
Warning copy (verbatim)
- Heading: "You're approaching your plan limits"
- Body: "Upgrade to {next-tier-name} to avoid interruptions and keep growing."
- Button: See plans (outline)
Both buttons go to /app/billing.
Hero meter — Training content
The first meter, in its own larger card:
- Label: Training content
- Subtitle: "Total characters across every chatbot. This is your primary training limit — once you hit it, new URLs, files, and Q&As are rejected."
-
Used:
usage.chars_used || 0formatted with K / M suffixes -
Max:
plan_limits.max_chars_trainedformatted the same way - Progress bar colored per level: primary (ok), amber (warning), destructive (critical / full)
-
Footer (only when level is warning/critical/full AND a next tier exists): "{next-tier-name} gives you {N chars} · Upgrade for ${price}/{interval}" with "Upgrade for..." as a link to
/app/billing.
Two secondary meters
Side-by-side below the hero:
Messages
- Label: Messages
-
Subtitle:
-
When both
period_startandperiod_endare present: "{period_start} → {period_end}" - Otherwise: "This billing period"
-
When both
-
Empty-hint (shown when level is
ok): "When your chatbot runs out of messages, visitors see an error instead of a reply." -
Formatted with
toLocaleString()
Chatbots
- Label: Chatbots
- Subtitle: "Total active bots on your account"
-
Empty-hint (shown when level is
ok): "One use case per chatbot: separate bots for sales, support, and FAQ each train on their own content." -
Formatted with
toLocaleString()
Both secondary meters replace the empty-hint with "{next-tier-name}: {value} →" as a link when the level crosses into warning or worse.
What-you-get-next card
Shown only if a next-tier plan exists. Content:
- Eyebrow: "Unlocks on {next-tier-name}" (or "Get more with {next-tier-name}" when any meter is critical/full)
- Heading: "What you're missing on {current plan name or 'Free'}"
- Body: "Upgrade to {next-tier-name} for ${price}/{interval} and unlock:"
Bulleted list contains:
- One item for each feature that's present on the next tier but not the current plan (labels below)
- "{N} training chars (currently {M})"
- "{N} messages/mo (currently {M})"
Feature delta labels (verbatim from FEATURE_LABELS in Usage/Index.jsx)
These are used only on the usage page's what-you-get-next list — they differ slightly from the billing page's labels:
-
whatsapp→ "WhatsApp integration (10× engagement vs web)" -
telegram→ "Telegram integration" -
tools→ "AI Tools — lead capture, booking, email send, webhooks" -
handoff→ "Human handoff — seamlessly hand hot leads to your team" -
custom_branding→ "Remove ChatbotGen branding from the widget" -
priority_support→ "Priority support (24h response SLA)"
Right side of the card:
- When any meter is critical: a quiet "Go to billing →" link (since the critical banner above already has the primary CTA)
- Otherwise: a large Upgrade to {next-tier-name} → button
Operational-limits footer
A muted strip at the bottom:
Operational limits (per chatbot)
Documents: up to {max_trained_documents} · URLs: up to {max_trained_urls}
These two numbers come from plan_limits and are not rendered as meters — they're advisory per the seed comment ("loose operational caps only").
Loading state
If plan_limits or usage are missing, the page shows "Loading usage…" and nothing else.