Billing & Subscriptions
HostMetrics uses Stripe for subscription billing. The billing system manages plan tiers, payment methods, checkout, and subscription lifecycle.
Plan Tiers
Plans are stored in the plans table. Each tier defines:
- Monthly and annual pricing
- Feature limits (number of vehicles, investors, imports)
- Access to premium features (reports, fleet pages, toll sync)
The BillingCycleToggle component lets users switch between monthly and annual pricing views. PlanComparisonModal shows a side-by-side feature comparison.
Checkout Flow
User selects plan → Stripe Checkout session created
→ User completes payment on Stripe → Webhook fires
→ Subscription record created → User gains access
- User clicks upgrade on
CurrentPlanCard
- API creates a Stripe Checkout session
- User is redirected to Stripe’s hosted checkout page
- On success, Stripe sends a webhook to the app
- The webhook handler creates/updates the
subscriptions record
Subscription Lifecycle
| Status | Meaning |
|---|
active | Subscription is current and paid |
past_due | Payment failed, grace period active |
cancelled | User cancelled, access until period end |
expired | Subscription period ended |
The CancelSubscriptionDialog handles cancellation with confirmation and reason collection.
Payment Methods
Users manage saved cards via PaymentMethodsCard and AddPaymentMethodDialog. Payment methods are stored in Stripe and referenced in the payment_methods table.
Customer Portal
The StripeConnectButton redirects users to Stripe’s Customer Portal where they can:
- Update payment methods
- View invoice history
- Download receipts
- Manage subscription
Webhook Processing
The Stripe webhook route processes these events:
| Event | Action |
|---|
checkout.session.completed | Create subscription record |
invoice.paid | Update subscription status, create invoice record |
invoice.payment_failed | Mark subscription as past_due |
customer.subscription.updated | Sync plan changes |
customer.subscription.deleted | Mark subscription as cancelled |
The webhook endpoint must verify Stripe’s signature to prevent spoofing. The signing secret is configured via environment variable.
Key Components
| Component | Purpose |
|---|
BillingSection | Main billing page layout |
CurrentPlanCard | Shows active plan with upgrade option |
PlanComparisonModal | Side-by-side plan features |
BillingCycleToggle | Monthly/annual toggle |
PaymentMethodsCard | Saved payment methods |
OrderHistoryTable | Past invoices and receipts |
UsageLimitsCard | Current usage vs plan limits |
PromoCodeCard | Apply promotional codes |
Key Files
| File | Purpose |
|---|
src/lib/db/billing.ts | Subscription and plan database operations |
src/hooks/useBilling.ts | Billing state and actions hook |
src/app/api/stripe/webhook/route.ts | Stripe webhook handler |