Plans & Products
Learn how to manage plans and products in your application.
Plans and products are defined in config/billing.config.ts. This configuration determines what plans are available, their pricing, and how they appear in your pricing table.
Plan Types
The starter kit supports several plan types:
Free Plan
The free plan is the default plan for users who haven't purchased any paid plans. It provides limited access to your product.
export const billingConfig = {
plans: {
free: {
id: 'free',
name: 'Free',
description: 'Get started with basic features',
isFree: true,
features: [
'Up to 3 team members',
'Basic analytics',
'Community support'
],
limits: {
maxMembers: 3,
maxStorage: 1 // GB
}
// No prices needed for free plans
}
}
};Subscription Plans
Subscription plans charge users on a recurring basis (monthly, yearly, etc.):
import { env } from '@/lib/env';
export const billingConfig = {
plans: {
pro: {
id: 'pro',
name: 'Pro',
description: 'For growing teams',
recommended: true, // Highlights this plan in the pricing table
features: [
'Unlimited team members',
'Advanced analytics',
'Priority support',
'100 GB storage'
],
limits: {
maxMembers: -1, // unlimited
maxStorage: 100 // GB
},
prices: [
{
id: 'pro_monthly',
stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY ?? '',
type: 'recurring',
interval: 'month',
intervalCount: 1,
amount: 2900, // $29.00 in cents
currency: 'usd',
seatBased: true, // Per-seat pricing
trialDays: 14 // Optional: 14-day free trial
},
{
id: 'pro_yearly',
stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY ?? '',
type: 'recurring',
interval: 'year',
intervalCount: 1,
amount: 27800, // $278.00 in cents
currency: 'usd',
seatBased: true,
trialDays: 14
}
]
}
}
};One-Time Purchase Plans
One-time purchase plans charge users a single upfront payment:
import { env } from '@/lib/env';
export const billingConfig = {
plans: {
lifetime: {
id: 'lifetime',
name: 'Lifetime',
description: 'Pay once, use forever',
features: [
'All Pro features',
'Lifetime updates',
'Priority support for 1 year'
],
limits: {
maxMembers: -1,
maxStorage: 100
},
prices: [
{
id: 'lifetime_once',
stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_LIFETIME ?? '',
type: 'one_time',
amount: 49900, // $499.00 in cents
currency: 'usd'
}
]
}
}
};Enterprise Plan
Enterprise plans show up in the pricing table with a link to a contact form:
export const billingConfig = {
plans: {
enterprise: {
id: 'enterprise',
name: 'Enterprise',
description: 'For large organizations with custom needs',
isEnterprise: true,
features: [
'Everything in Pro',
'Dedicated account manager',
'Custom SLA',
'Unlimited storage',
'SSO / SAML'
],
limits: {
maxMembers: -1,
maxStorage: -1
}
// No prices needed - users contact you directly
}
}
};Price Properties
Each price object supports the following properties:
id: Unique identifier for the price (e.g.,"pro_monthly")type:"recurring"or"one_time"stripePriceId: The Stripe Price ID (from environment variables, starts withprice_)interval: For recurring plans:"month","year","week"or"day"intervalCount: Number of intervals to bill (defaults to 1)amount: The price amount (in cents for Stripe)currency: Currency code (e.g.,"usd","eur")trialDays: Optional trial period in daysseatBased: Iftrue, price is per seat (multiplies by number of organization members)
Plan Configuration Options
recommended: Highlights the plan in the pricing tablehidden: Hides the plan from the pricing table (useful for grandfathering old plans)
Creating Plans in Stripe
- Go to your Stripe Dashboard
- Navigate to Products > Add product
- Create your product with pricing
- Copy the Price ID (starts with
price_) - Add it to your environment variables:
NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY=price_xxxxx
NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY=price_xxxxx
NEXT_PUBLIC_STRIPE_PRICE_LIFETIME=price_xxxxxPlan Limits
You can define plan limits in config/billing.config.ts:
export const billingConfig = {
plans: {
pro: {
// ... prices
limits: {
maxMembers: 10, // Maximum organization members
maxProjects: 50 // Maximum projects
// Add your own limits
}
}
}
};These limits are then checked in your application logic to enforce plan restrictions.