15 — Billing & Usage (Blueprint Screen 12, `/app/testimonials/billing`)
Cursor-ready plan: plan status, usage meters, overage behavior, warnings, and upgrade flow for testimonial app billing.
15 — Billing & Usage (Blueprint Screen 12)
Section titled “15 — Billing & Usage (Blueprint Screen 12)”Source: 02-Implementation-Blueprint.md — Screen 12 - Billing & Usage (/app/testimonials/billing).
Naming note: This is blueprint “Screen 12” (billing). It is not related to the file-number convention of other docs.
Product alignment: 03-Pricing-Options.md — especially Option B (Hybrid Base + Metered Overage, recommended) and Implementation Notes for Billing Screen.
This document is a build spec only. No code changes are implied until a task references this file.
Prerequisites: baseline subscription plumbing already exists in boilerplate (ShopSubscription, one-time charge model, app subscription webhooks), and testimonial usage counters are defined (see section 3).
0) Goal (one sentence)
Section titled “0) Goal (one sentence)”Merchants open /app/testimonials/billing to see current plan, period usage (requests, storage, processed video minutes), overage behavior and estimated charges, warning states, and a clear upgrade/buy flow.
1) Route and file
Section titled “1) Route and file”| Item | Value |
|---|---|
| Suggested file | app/routes/app.testimonial-billing.jsx (blueprint §6). |
| URL | /app/testimonials/billing. |
Auth: authenticate.admin(request); all data is scoped by shopId.
Nav: Billing & Usage link under testimonial section.
2) Pricing model to implement (v1)
Section titled “2) Pricing model to implement (v1)”From 03-Pricing-Options.md:
- Use Option B: Hybrid Base + Metered Overage.
- Starter/Growth/Scale tier examples are already defined.
- Overages should be explicit and transparent.
2.1 Billable dimensions (from blueprint Screen 12 + pricing notes)
Section titled “2.1 Billable dimensions (from blueprint Screen 12 + pricing notes)”requests_usedstorage_gb_usedprocessed_video_minutes_used
These are the only required usage counters for v1 UI. Anything else is optional and should not block this screen.
3) Data model additions (if missing)
Section titled “3) Data model additions (if missing)”Existing schema currently has chat-era billing fields. For testimonial billing, add dedicated fields/models and avoid mixing semantics.
3.1 Recommended model: TestimonialBillingCycle
Section titled “3.1 Recommended model: TestimonialBillingCycle”One row per shop per billing cycle.
Suggested fields:
id,shopIdcycleStartAt,cycleEndAt,nextResetAtplanCode(starter,growth,scale)requestsIncluded,storageGbIncluded,videoMinutesIncludedrequestsUsed,storageGbUsed,videoMinutesUsedoverageRequests,overageStorageGb,overageVideoMinutesoverageAmountCentsEstimatedoverageEnabled(boolean)status(open,finalized,invoiced)- timestamps
Unique/index:
@@unique([shopId, cycleStartAt, cycleEndAt])- indexes on
(shopId, status),(shopId, cycleEndAt)
3.2 Alternative (lighter v1)
Section titled “3.2 Alternative (lighter v1)”Store counters on Shop + derive cycle from ShopSubscription.currentPeriodEnd. This is faster initially but harder for audits/history. Prefer dedicated cycle rows if possible.
3.3 Plan catalog source
Section titled “3.3 Plan catalog source”Reuse or extend existing plan helper module (e.g., plans.server.js) with testimonial-oriented limits/rates:
- included limits
- overage rates
- whether overage is allowed per plan
4) Usage ingestion rules
Section titled “4) Usage ingestion rules”Usage counters must update from real events:
- Requests used: increment when request is actually sent (pipeline from
07), not when scheduled. - Storage GB used: computed from successful media assets (
fileSizeBytes) fromTestimonialMediaAsset. - Processed video minutes: sum of
durationSec / 60for video assets that reached processed/ready state.
4.1 Write path strategy
Section titled “4.1 Write path strategy”Choose one and document:
- Event-driven increments during normal flows, with periodic reconciliation job.
- Nightly recompute from source tables for accuracy.
Recommended: event-driven + nightly reconciliation for correctness.
5) Loader contract for billing page
Section titled “5) Loader contract for billing page”Return one payload with:
- Current plan details
- Current cycle range and next reset date
- Usage vs included for 3 meters
- Overages (units + estimated amount)
- Warning flags (80%, 100%, overage active)
- Upgrade CTA target
Example shape:
{ "plan": { "code": "growth", "name": "Growth", "priceUsd": 49 }, "cycle": { "start": "2026-05-01", "end": "2026-05-31", "nextReset": "2026-06-01" }, "usage": { "requests": { "used": 1730, "included": 2000, "pct": 86.5 }, "storageGb": { "used": 21.4, "included": 25, "pct": 85.6 }, "videoMinutes": { "used": 412, "included": 500, "pct": 82.4 } }, "overage": { "enabled": true, "units": { "requests": 0, "storageGb": 0, "videoMinutes": 0 }, "estimatedCents": 0 }, "alerts": { "warn80": true, "hit100": false, "overageActive": false }}6) UI structure (Polaris)
Section titled “6) UI structure (Polaris)”Follow blueprint Screen 12 fields exactly:
- Current plan card
- Plan name, monthly price, billing cycle dates
- Period usage card group
- Requests used
- Storage used (GB)
- Processed video minutes
- Each with progress bar + “used / included”
- Overage settings/toggles
- Allow overages toggle (if plan supports)
- Overage unit rates
- Estimated overage this cycle
- Upgrade CTA
- Button to plan selection/upgrade flow
6.1 Alerts (from pricing doc §10)
Section titled “6.1 Alerts (from pricing doc §10)”- Show warning at >=80% for each meter
- Show limit reached at >=100%
- Show “overage billing active” if any overage units > 0
Use non-blocking banners unless merchant action is required.
7) Actions on page
Section titled “7) Actions on page”Required:
toggle_overage_enablednavigate_upgrade
Optional:
buy_usage_pack(if you add add-on packs later)
All writes should validate shop ownership and current subscription status.
8) Upgrade and billing flow integration
Section titled “8) Upgrade and billing flow integration”Reuse existing billing infrastructure patterns in repo (subscription confirm routes/webhooks) but move semantics from chat credits to testimonial meters.
Minimum behavior:
- If no active subscription: show “Select a plan”.
- If active: show current plan and allow upgrade/downgrade path.
- On webhook updates (
app_subscriptions/update), refresh plan + cycle data idempotently.
9) Reconciliation and correctness
Section titled “9) Reconciliation and correctness”Add a scheduled job (daily) to recompute current cycle usage from source-of-truth tables:
- sent requests
- media assets size
- processed video durations
If mismatch > tolerance, correct the cycle row and log an internal warning.
This avoids drift from partial failures.
10) Testing checklist (acceptance criteria)
Section titled “10) Testing checklist (acceptance criteria)”- Current plan and cycle dates render for active shop.
- Requests/storage/video counters match seeded source tables.
- 80% and 100% thresholds trigger correct banners.
- Overages compute expected units and estimated amount.
- Toggle overage setting persists and reload reflects value.
- Shop without plan sees upgrade CTA, not broken metrics.
- Cross-shop access is blocked.
11) Implementation order (for Cursor)
Section titled “11) Implementation order (for Cursor)”- Define testimonial plan limits/rates in plan helper module.
- Add billing cycle/counter schema (or chosen lightweight approach).
- Wire usage increments from send pipeline (
07) and media processing. - Build loader aggregates + page payload.
- Build Polaris UI for plan, meters, overage, CTA.
- Add overage toggle action.
- Add daily reconciliation job.
12) References
Section titled “12) References”02-Implementation-Blueprint.md— Screen 1203-Pricing-Options.md— Option B + billing screen notes07-email-sms-request-delivery-pipeline.md— sent requests usage source06-public-submission-page-screen-13.md+ media processing path — submission/media usage source
13) Note on numbering
Section titled “13) Note on numbering”This folder already includes 05–14 numbered plans. This file is 15-… to keep sequence stable.