Skip to main content
<UserProfile> is the whole account area: a sidebar and three tabs.
Picking a plan there behaves like <PricingTable>: a confirm step and an in-place switch for whoever’s already subscribed, a straight checkout for whoever isn’t. Show only the tabs you need:
Add your own:
To drive tabs from your router, pass activeTab and onTabChange.

Using the blocks on their own

If you already have a settings page, mount just the part you want. Each one works standalone:

<UsageMeters>

Shows what has been consumed against the plan’s limits. It only meters what can be metered: features with no ceiling are hidden, and the rows closest to their limit come first, so what is about to run out is at the top.
Pass labels if your feature keys are not the wording you want users to read:

<SubscriptionCard>

Current plan, price, renewal date, and a button through to your payment provider’s portal. Renders a real “you are on the free plan” state rather than nothing when there is no subscription.

Paywalling a feature

<UpgradePrompt> renders your feature when the user is entitled to it, and an upgrade message when they are not:
The message follows the reason. Someone who ran out of a monthly quota sees a different sentence from someone whose plan never included the feature — telling the first to upgrade when they only need to wait for the reset is a good way to lose them.

After checkout

<CheckoutResult> renders a checkout outcome screen - mount it wherever your app confirms a checkout, passing the outcome:
It confirms the subscription really exists before saying so. Coming back from Stripe only means the payment went through on the provider’ side — the subscription lands a moment later, over a webhook. This waits for it instead of announcing a success the rest of your app cannot see yet.