General
Billing

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.

config/billing.config.ts
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.):

config/billing.config.ts
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:

config/billing.config.ts
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:

config/billing.config.ts
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 with price_)
  • 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 days
  • seatBased: If true, price is per seat (multiplies by number of organization members)

Plan Configuration Options

  • recommended: Highlights the plan in the pricing table
  • hidden: Hides the plan from the pricing table (useful for grandfathering old plans)

Creating Plans in Stripe

  1. Go to your Stripe Dashboard
  2. Navigate to Products > Add product
  3. Create your product with pricing
  4. Copy the Price ID (starts with price_)
  5. Add it to your environment variables:
.env
NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY=price_xxxxx
NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY=price_xxxxx
NEXT_PUBLIC_STRIPE_PRICE_LIFETIME=price_xxxxx

Plan Limits

You can define plan limits in config/billing.config.ts:

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.