Help centre Families Coaches Support

Littles Baby Tracker

Help for families and coaches

Site Tools


technical:features:04_subscriptions_billing_and_premium_access

04 — Subscriptions, billing and premium access

Technical reference. For task-based help, see the corresponding user guide.
Documentation status: complete for the current implementation

Reviewed: 2026-07-22

Primary users: families, coaches and the platform owner

Surfaces: mobile WebView, coach admin portal, owner portal, native wrapper and platform API

Purpose

This feature turns store, Stripe, coach-sponsored and manual access records into one trusted premium decision. Families can buy or restore direct access in the phone app or receive access through a coach. Coaches buy an unlimited client-sharing plan on the web. The platform—not the browser or native receipt alone—decides whether premium tools are available.

Activity tracking remains available when premium is inactive. Analysis and other explicitly premium experiences use the backend-resolved permission.

Product plans

Audience Choice Current catalogue price Purchase system
Family Monthly £6.99/month App Store or Google Play through RevenueCat/native bridge
Family Yearly £50/year App Store or Google Play through RevenueCat/native bridge
Coach Monthly unlimited £15.99/month Stripe Checkout on the coach portal
Coach Six-month unlimited £71.99/6 months Stripe Checkout on the coach portal
Coach Yearly unlimited £128.99/year Stripe Checkout on the coach portal

The family screen advertises a two-week free trial; actual localized price/trial eligibility shown by the store remains authoritative. Coach introductory offers, when returned by the platform, show their claim deadline, initial amount/duration and the selected cadence's automatic renewal terms.

Entry points

Surface Entry point Function
Family mobile /family/subscription Plan selection, purchase/management and restore.
Family mobile /family/access Current premium source, coach access, expiry/grace and direct plan choices.
Family mobile /analysis Premium gate with subscription CTA when direct access is unavailable.
Coach mobile /coach/subscription Read-only status, renewal/cancellation detail and handoff to web billing.
Coach admin portal /subscription Stripe plan selection, Checkout, recovery, Customer Portal and cancellation.
Owner portal /billing Revenue detail and cumulative coach/family registration-cohort acquisition by day, month or quarter.

Family access resolution

The family summary includes one resolved premium result. Common sources are:

  • directSubscription — verified family App Store/Google Play entitlement;
  • coachInvite — an active coach assignment/support entitlement;
  • platformPractice — practice policy-backed access; and
  • manualComp — explicitly granted manual access.

The result includes active, source, expiry and a disabledReason. The UI labels active, grace, expired, revoked, billing-inactive and organization-suspended states from that result instead of reconstructing billing rules locally.

Direct family purchase

  1. The screen requests the wrapper's live RevenueCat products and displays localized prices; catalogue prices are only a fallback display.
  2. The family selects monthly or yearly and starts the narrow native purchase bridge call using the platform user ID.
  3. A successful store response is sent to POST /families/me/subscription/store/verify.
  4. The server queries RevenueCat's active premium entitlement (including linked legacy IDs where applicable), updates direct access, and returns a fresh family summary.
  5. Only after server verification succeeds does the WebView finish the native transaction and announce that premium tools are available.
  6. Cancellation/renewal lifecycle changes are later synchronized by RevenueCat webhooks and by explicit verification/restore.

Restore purchase

  1. Restore purchase asks RevenueCat for the signed-in family identity.
  2. If nothing active is found, the UI reports that no subscription was available without treating it as a crash.
  3. A found purchase follows the same server-verification path as a new purchase.
  4. Store account management opens the platform-specific external management URL; the app never attempts to cancel an Apple/Google subscription directly.
Native condition: a real family purchase or restore requires the supported phone wrapper and configured RevenueCat products. In an ordinary browser the plans can be displayed, but browser-local fallback data is not a verified store entitlement and cannot unlock server premium access.

Coach-sponsored access and grace

  1. Accepting an eligible coach invitation creates a coachInvite entitlement tied to the assignment/support period.
  2. Coach or organization billing becoming inactive disables premium analysis but does not prevent family tracking.
  3. When ordinary coach support ends or either side disconnects, coach read/edit access ends immediately and family premium enters a seven-day grace period.
  4. The family access screen shows the support-ended date, grace days remaining and grace end, then offers direct plans.
  5. Practice policy can preserve sponsored premium for specific platform-owned cases; this does not restore coach visibility to expired/revoked clients.
  6. An active direct store subscription is independent of coach access. A coach invite triggers the explicit store-conflict acknowledgement described in Feature 03.

Coach web billing

Status and capacity

GET /coach/subscription returns the latest subscription, current-family usage, capacity metadata, latest Checkout attempt and any introductory offer. Current-family usage includes active, paused and not-yet-started support that remains on the current client list. The normal plan uses an effectively unlimited family limit; finite capacity is retained only for deliberate legacy/manual test records.

Subscription statuses are active, trialing, pastDue, canceled and suspended. Provider is stripe or manual.

Start or recover Checkout

  1. Inactive coaches and coaches moving from manual access can select monthly, six-month or yearly cadence.
  2. POST /coach/subscription/stripe/checkout creates a server-authorized Stripe Checkout URL with safe success/cancel return locations.
  3. An incomplete/processing/action-required Checkout attempt is shown with the platform message, amount context and Return to Stripe checkout when a recovery URL is available.
  4. Stripe webhook verification, not the redirect alone, is the passive source of truth for subscription activation and future lifecycle changes.

Manage and cancel

  1. Active Stripe subscriptions with a customer ID can open Customer Portal through POST /coach/subscription/stripe/portal.
  2. Direct cancellation requires a confirmation. The platform/Stripe response normally marks cancelAtPeriodEnd and the UI states the date through which access continues and that no further renewal will occur.
  3. Manual access is labelled explicitly and is not misrepresented as Stripe billing.
  4. The phone coach screen is status-led and read-only. It shows plan/status, payment or access-until information and opens the coach portal through a short-lived handoff URL. It never embeds Stripe or exposes native store purchase/restore controls for coaches.

Owner acquisition cohorts

GET /admin/billing/summary includes an acquisition object calculated by the trusted API. The browser renders that result and never reads users, entitlements or subscriptions directly from Supabase.

  1. views.daily contains 30 UTC days, views.monthly contains 12 UTC months, and views.quarterly contains 8 UTC calendar quarters. Each window ends with the interval containing generatedAt; since is inclusive and until is the exclusive start of the next interval.
  2. Every view has mode=cumulative. Each periodStart point contains the running total from the beginning of its selected window through that period. Counts expose registrationOnly, subscriptions and activeOrTrialing for coaches and families. The narrower trialing count remains in the response for compatibility with the briefly released trial-only owner chart but is not the dashed series.
  3. The original cohortBasis=registrationMonth, interval=month, monthStart, window, totals and 12-point points fields remain non-cumulative for backward compatibility with a cached older owner frontend.
  4. A user with the coach role is included in the coach cohort for users.created_at; a user with the family role is included in the family cohort. A dual-role user contributes once to each applicable audience.
  5. Coach subscriptions means the user has at least one production Stripe subscription record. Manual owner-granted access and stripeMode=sandbox are not conversions.
  6. Family subscriptions means the user has at least one production direct-subscription entitlement. Production trial starts count; storeEnvironment=sandbox does not.
  7. activeOrTrialing is a subset of subscriptions, not a third additive acquisition category. A coach is included when their latest production Stripe record has status=active or status=trialing. A family is included when their latest production direct-subscription entitlement is effectively active; this includes paid active access and a current store trial.
  8. Subscription classification is historical (ever subscribed), not current access. Canceled, expired or past-due production records remain conversions. A later conversion therefore moves the user from the registration-only cumulative line to the subscription cumulative line at their original registration period.
  9. registrationOnly is the complementary count for registered users without a qualifying production subscription.
  10. Imported users are bucketed by the platform users.created_at value. If an import could not preserve a legacy signup timestamp, the cohort reflects the platform import date.

The chart defaults to coaches and months, offers Coaches/Families and Days/Months/Quarters switches, and uses cumulative Subscription and Registration-only lines plus a dashed green Active-or-trialing subset line. Hovering or focusing a plotted point renders an SVG tooltip with the full UTC period label and all three cumulative values. The selected-audience totals include the cohort conversion percentage for the selected window. It is not a provider cash, invoice or proceeds report.

Premium feature gates

Capability Inactive premium behavior
Activity logging, histories and timers Remains available.
Family home and baby profiles Remain available.
Analysis and trends Family sees plan choices/CTA; coach view receives an inactive-access state.
Coach invitation creation/redemption Blocked when the coach subscription or organization is ineligible.
Coach family access Depends on both assignment/support state and organization/billing state, not subscription alone.

Development builds may explicitly allow inactive-premium analysis for test fixtures. That override is not a production entitlement and must not be used as an authorization rule.

Validation and user-visible states

State Expected behavior
Loading Keep purchase/restore/Checkout actions disabled while the authoritative status is fetched.
Store products unavailable Show catalogue choices where possible, but do not claim verified access.
Purchase cancelled by user Return to the plan screen without creating a platform entitlement.
Store verification fails Do not finish/announce access; present a retryable API error.
Restore finds nothing Show a neutral “no active subscription” message.
Grace period Keep premium active and show the exact support/grace dates and direct-subscription CTA.
Billing inactive or suspended organization Keep tracking usable; block premium analysis and coach sharing.
Stripe Checkout incomplete Show recovery status and recovery URL when supplied.
Cancellation scheduled Keep access through the returned period end and label the non-renewing state.
Manual coach subscription Show manual access; do not offer Stripe management as though a customer exists.

Platform API contract

Method and path Role Authentication
GET /families/me Return the family summary and resolved premium result. Signed-in family/authorized subject
POST /families/me/subscription/store/verify Verify RevenueCat premium and synchronize direct access. Signed-in family self-mode
GET /coach/subscription Return coach subscription, usage, Checkout attempt and offer state. Signed-in coach
POST /coach/subscription/stripe/checkout Create cadence-specific Stripe Checkout. Signed-in coach
POST /coach/subscription/stripe/portal Create a Stripe Customer Portal session. Stripe-backed signed-in coach
POST /coach/subscription/stripe/cancel Schedule/carry out server-authorized cancellation. Stripe-backed signed-in coach
POST /coach/admin-portal-link Create the mobile-to-web coach portal handoff. Signed-in coach
POST /billing/revenuecat/webhooks Synchronize family store lifecycle. Verified provider webhook
POST /billing/stripe/webhooks Synchronize coach Stripe lifecycle. Signature-verified provider webhook
GET /admin/billing/summary Return owner revenue/access detail and coach/family acquisition cohorts. Genuine super-admin

The legacy POST /coach/subscription/store/verify remains for migrated coach store subscriptions. Current coach purchase UX is Stripe web billing only.

Authorization and security rules

  1. Native/store purchase output is evidence to verify, not an entitlement the client can assert.
  2. Stripe Checkout/Portal URLs are created server-side for the signed-in coach and safe return paths.
  3. Webhook signatures are verified before billing state is synchronized.
  4. Premium access is resolved with assignment, entitlement, organization and subscription state on every trusted request.
  5. Families cannot use coach billing routes; coaches cannot use native family store purchase controls.
  6. No service-role key, webhook secret, receipt token or Stripe customer secret is returned in these user-facing screens.

Acceptance checklist

  1. Family monthly/yearly products use localized store prices when available and only unlock after server verification.
  2. Restore handles both an active purchase and an empty result clearly.
  3. Coach-sponsored access follows the assignment/support period and enters the documented grace state after support ends.
  4. Inactive premium never blocks ordinary activity logging.
  5. Inactive coaches can select cadence and enter Stripe Checkout; incomplete Checkout can be resumed.
  6. Active Stripe coaches can open Portal and confirm cancellation; manual access is labelled separately.
  7. The coach phone screen performs a web handoff and contains no coach store/embedded Stripe purchase controls.
  8. All premium decisions come from platform responses rather than local billing flags.
  9. The owner acquisition graph returns ordered cumulative 30-day, 12-month and 8-quarter UTC series and switches between coach and family counts.
  10. Manual coach access and sandbox coach/family records remain excluded from acquisition subscription conversion.

Source evidence

Mobile web and wrapper

  • mobile-web/src/routes/FamilyAccessScreen.tsx
  • mobile-web/src/components/FamilySubscriptionPlanGrid.tsx
  • mobile-web/src/routes/CoachSubscriptionScreen.tsx
  • mobile-web/src/routes/AnalysisScreen.tsx
  • mobile-web/src/webview/native-messages.ts
  • mobile-wrapper/src/native/coachSubscriptions.ts

Coach portal

  • admin-web/src/routes/CoachBillingPanel.tsx
  • admin-web/src/api/client.ts

Owner portal

  • owner-web/src/routes/OwnerAcquisitionChart.tsx
  • owner-web/src/routes/OwnerBillingPanel.tsx
  • owner-web/src/api/client.ts

Platform and contracts

  • platform/apps/api/src/routes/family-routes.ts
  • platform/apps/api/src/routes/coach-routes.ts
  • platform/apps/api/src/routes/store-subscription-routes.ts
  • platform/apps/api/src/services/admin-billing-summary-service.ts
  • platform/packages/shared/src/admin.ts
  • platform/packages/shared/src/billing.ts
  • platform/packages/shared/src/coach.ts
  • platform/packages/shared/src/access.ts
  • platform/docs/multi-tenancy/05-development-plan.md