Plans & Prices
NuxtBase ships with three internal plan keys:
freepluspro
Those keys are not just display labels. They are used across billing logic, Stripe price mapping, subscription sync, and some feature entitlements.
The Shipped Plan Model
Section titled “The Shipped Plan Model”The default plan definitions look like this:
const plans = [ { key: "free", intervals: [], defaultCreditsQuota: 100 }, { key: "plus", intervals: ["monthly", "yearly"], defaultCreditsQuota: 500 }, { key: "pro", intervals: ["monthly", "yearly"], defaultCreditsQuota: 2000 },];What matters here:
freehas no recurring intervals, so it is not a checkout targetplusandproare the two paid plans the billing APIs understand out of the boxplussits betweenfreeandproin the default quota model- monthly and yearly billing are supported for both paid plans
How Stripe Price Mapping Works
Section titled “How Stripe Price Mapping Works”The template resolves paid plans from four runtime config values:
NUXT_STRIPE_PRO_MONTHLY_PRICE_ID=price_...NUXT_STRIPE_PRO_YEARLY_PRICE_ID=price_...NUXT_STRIPE_PLUS_MONTHLY_PRICE_ID=price_...NUXT_STRIPE_PLUS_YEARLY_PRICE_ID=price_...At runtime, checkout and webhook sync use those price IDs to answer two questions:
- which Stripe price should be used for a new checkout
- which internal plan and interval a Stripe subscription belongs to
If the mapping is wrong, the app can still receive Stripe events, but it will not resolve plan identity correctly.
Who Can Change Billing
Section titled “Who Can Change Billing”Billing is not editable by every member of an organization.
The template uses requireActiveBillingManager(), which means only these roles
can start checkout or mutate subscriptions for the active organization:
owneradmin
Regular members can still open the billing page, but they get a view-only state in the dashboard UI.
What The Billing Page Shows
Section titled “What The Billing Page Shows”The dashboard billing screen combines three kinds of data:
- the current effective plan for the active organization
- the current billing interval if the organization is on a paid plan
- usage UI such as project count and AI credits quota
When the API cannot find an operable subscription, it returns a free-plan response instead of an error:
const FREE_RESPONSE = { status: "none", planId: "free", planName: "Free Plan", isPro: false, interval: null,};That is why a fresh organization still renders a usable billing page.
Development-Only Price Overrides
Section titled “Development-Only Price Overrides”The plan-change endpoint supports an explicit priceId override only in
development and test.
That is a useful local escape hatch when you are testing Stripe price experiments, but it is not part of the normal production flow. In production, the app expects the canonical env-based mapping to be correct.
Safe Change Order
Section titled “Safe Change Order”If you want to customize plans, do it in this order:
- decide whether you are keeping
free,plus, andproor replacing the model - update Stripe products and recurring prices
- update the env price ID mapping
- verify checkout creates the expected subscription
- verify the billing page shows the correct plan and interval after webhook sync