Plan Customization
Configure, enable, disable, and customize your SaaS pricing plans
Easily customize your pricing plans - change prices, enable/disable plans, or add new ones. No code changes required for basic plan management.
Quick Reference
- Change prices: Edit environment variables
- Hide plans: Set
PLAN_X_ENABLED=false - Show plans: Set
PLAN_X_ENABLED=true - Add new plans: Edit
src/lib/billing/plans.ts
Plan Structure
The starter comes with three pre-configured plans:
- Free: $0 - Basic features for trying out the platform
- Pro: $29/mo or $290/yr - For power users and professionals
- Enterprise: $99/mo or $990/yr - For businesses with custom needs
You can customize any aspect of these plans or create entirely new ones.
Common Scenarios
Single Paid Product (No Free Plan)
Perfect for selling a single product or service. Users must subscribe to use your SaaS.
Environment variables:
1# Disable free plan, enable only Pro2PLAN_FREE_ENABLED="false"3PLAN_PRO_ENABLED="true"4PLAN_ENTERPRISE_ENABLED="false"5 6# Set your product price7PLAN_PRO_MONTHLY="29"8PLAN_PRO_YEARLY="290"Result
Freemium Model (Free + Pro)
Offer a free tier with basic features and a paid tier with premium features.
1# Enable free and pro, disable enterprise2PLAN_FREE_ENABLED="true"3PLAN_PRO_ENABLED="true"4PLAN_ENTERPRISE_ENABLED="false"5 6# Adjust Pro pricing7PLAN_PRO_MONTHLY="19"8PLAN_PRO_YEARLY="190"All Plans Enabled (Default)
Use all three plans for a complete tiered offering.
1# All plans enabled (this is the default if not specified)2PLAN_FREE_ENABLED="true"3PLAN_PRO_ENABLED="true"4PLAN_ENTERPRISE_ENABLED="true"5 6# Customize all prices7PLAN_PRO_MONTHLY="19"8PLAN_PRO_YEARLY="190"9PLAN_ENTERPRISE_MONTHLY="99"10PLAN_ENTERPRISE_YEARLY="990"One-Time Purchase Only
Sell lifetime access instead of subscriptions. This requires editing the plans file.
1pro: {2 id: "pro",3 name: "Lifetime Pro",4 description: "One-time purchase for lifetime access",5 // ... other config6 priceMonthly: undefined, // Hide monthly7 priceYearly: undefined, // Hide yearly8 priceOneTime: 299, // Show one-time price9 // ...10}Changing Plan Prices
All plan prices can be customized via environment variables - no code changes needed!
Update Environment Variables
Edit your .env.local file with your desired prices:
1# Pro Plan Pricing2PLAN_PRO_MONTHLY="29" # Change from default $193PLAN_PRO_YEARLY="290" # Change from default $1904# PLAN_PRO_ONE_TIME="299" # Optional: one-time lifetime price5 6# Enterprise Plan Pricing7PLAN_ENTERPRISE_MONTHLY="99" # Keep at $99 or change8PLAN_ENTERPRISE_YEARLY="990" # Keep at $990 or change9# PLAN_ENTERPRISE_ONE_TIME="499" # Optional: one-time lifetime priceRemember
Update Payment Provider Prices
Environment variables only change the display price. You must also update the actual prices in your payment provider:
- Stripe: Update the Price objects in your Stripe Dashboard
- LemonSqueezy: Update the variant prices in your LemonSqueezy Dashboard
Adding a New Plan
To add a completely new plan (e.g., "Team" or "Starter"), you'll need to edit the plans configuration file.
Edit Plans Configuration
Open src/lib/billing/plans.ts and add your new plan to the PLANS object:
1export const PLANS = {2 free: { ... },3 starter: { // Your new plan4 id: "starter",5 name: "Starter",6 description: "Perfect for small teams getting started",7 limits: {},8 // Stripe prices9 stripePriceMonthly: process.env.STRIPE_PRICE_STARTER_MONTHLY || null,10 stripePriceYearly: process.env.STRIPE_PRICE_STARTER_YEARLY || null,11 // LemonSqueezy variants12 lemonVariantMonthly: process.env.LEMONSQUEEZY_VARIANT_STARTER_MONTHLY || null,13 lemonVariantYearly: process.env.LEMONSQUEEZY_VARIANT_STARTER_YEARLY || null,14 // Display pricing15 priceMonthly: parseInt(process.env.PLAN_STARTER_MONTHLY || "9", 10),16 priceYearly: parseInt(process.env.PLAN_STARTER_YEARLY || "90", 10),17 features: [18 "Up to 5 team members",19 "Basic analytics",20 "Email support",21 "1GB storage",22 ],23 isHidden: !isPlanEnabled('starter', true),24 },25 pro: { ... },26 enterprise: { ... },27} as const;Add Environment Variables
Add the new plan's environment variables to .env.example and .env.local:
1# Starter Plan (new plan)2PLAN_STARTER_ENABLED="true"3PLAN_STARTER_MONTHLY="9"4PLAN_STARTER_YEARLY="90"5STRIPE_PRICE_STARTER_MONTHLY="price_..."6STRIPE_PRICE_STARTER_YEARLY="price_..."7LEMONSQUEEZY_VARIANT_STARTER_MONTHLY="..."8LEMONSQUEEZY_VARIANT_STARTER_YEARLY="..."Create Stripe/LemonSqueezy Products
Create corresponding products in your payment provider dashboard and copy the price/variant IDs.
Plan Features
Customize the feature list shown on your pricing page by editing the features array in each plan:
1pro: {2 // ... other config3 features: [4 "All basic features",5 "Priority support",6 "Advanced analytics",7 "Custom integrations",8 "API access", // Add new features9 "Webhooks", // to any plan10 ],11 highlighted: true, // Makes this plan stand out on pricing page12}Feature Checklist Icons
Helper Functions
The plans system includes several helper functions you can use in your code:
1import { 2 PLANS, 3 getVisiblePlans, 4 getVisiblePlanIds, 5 getDefaultPlan,6 isFreePlan,7 hasPaidPlans,8 isFreemium 9} from "@/lib/billing/plans";10 11// Get all visible plans12const plans = getVisiblePlans();13 14// Check if user is on a free plan15const free = isFreePlan(userPlanId);16 17// Check if you have any paid plans enabled18const hasPaid = hasPaidPlans();19 20// Check if you're running a freemium model21const freemium = isFreemium();Next Steps
- Set up your payment providers (Stripe and/or LemonSqueezy)
- Configure your feature flags to gate features based on plans
- Customize your pricing page styling
- Test the full checkout flow before going live