General
Configuration

Billing Configuration

Configure plans, pricing, and credit packages.

The billing configuration file (config/billing.config.ts) contains settings for billing features, subscription plans, pricing, and credit packages for AI features.

Configuration File

The billing configuration is extensive and includes:

  • Billing settings: Enable/disable billing, default currency
  • Plans: Subscription plans with features, limits, and pricing
  • Credit packages: One-time credit purchases for AI features
  • Credit costs: Per-model pricing for AI usage
config/billing.config.ts
import { env } from '@/lib/env';

export const billingConfig = {
  // Enable/disable billing feature
  enabled: true,
  // Default currency
  defaultCurrency: 'usd',
  // Plans configuration
  plans: {
    // Free tier - no Stripe price needed
    free: {
      id: 'free',
      name: 'Free',
      description: 'Get started with basic features',
      isFree: true,
      features: [
        'Up to 3 team members',
        'Basic analytics',
        'Community support',
        '1 GB storage'
      ],
      limits: {
        maxMembers: 3,
        maxStorage: 1 // GB
      }
    },
    // Pro plan - main paid tier
    pro: {
      id: 'pro',
      name: 'Pro',
      description: 'For growing teams',
      recommended: true,
      features: [
        'Unlimited team members',
        'Advanced analytics',
        'Priority support',
        '100 GB storage',
        'Custom integrations',
        'API access'
      ],
      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
        },
        {
          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
        }
      ]
    },
    // Lifetime deal - one-time order
    lifetime: {
      id: 'lifetime',
      name: 'Lifetime',
      description: 'Pay once, use forever',
      features: [
        'All Pro features',
        'Lifetime updates',
        'Priority support for 1 year',
        '100 GB storage'
      ],
      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'
        }
      ]
    }
  }
} satisfies BillingConfig;

Configuration Options

Billing Settings

  • enabled: Enable/disable billing feature (default: true)
  • defaultCurrency: Default currency for pricing (default: "usd")

Plans

Each plan in the plans object has:

  • id: Unique identifier for the plan
  • name: Display name
  • description: Plan description
  • features: Array of feature strings
  • limits: Plan limits (members, storage)
  • prices: Array of price configurations

Plan Types

  • Free plans: Set isFree: true, no prices needed
  • Paid plans: Include prices array with Stripe price IDs
  • Enterprise plans: Set isEnterprise: true, typically no prices (contact sales)

Price Configuration

Each price has:

  • id: Unique price identifier
  • stripePriceId: Stripe Price ID from your Stripe dashboard
  • type: "recurring" or "one_time"
  • amount: Price in cents
  • currency: Currency code
  • interval: For recurring: "month", "year", "week", or "day"
  • intervalCount: Number of intervals
  • seatBased: Whether pricing is per-seat (optional)
  • trialDays: Trial period in days (optional)

Credit Packages

Credit packages are configured separately for one-time purchases:

config/billing.config.ts
export const creditPackages = [
  {
    id: 'credits_starter',
    name: 'Starter',
    description: 'Great for trying out AI features',
    credits: 10_000,
    bonusCredits: 0,
    priceAmount: 999, // $9.99 in cents
    currency: 'usd',
    stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_STARTER ?? '',
    popular: false
  },
  {
    id: 'credits_basic',
    name: 'Basic',
    description: 'For regular AI usage',
    credits: 50_000,
    bonusCredits: 5_000, // 10% bonus
    priceAmount: 3999, // $39.99
    currency: 'usd',
    stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_BASIC ?? '',
    popular: true
  }
];

Credit Costs

Credit costs define pricing per AI model:

config/billing.config.ts
export const creditCosts = {
  'gpt-4o-mini': {
    input: 1, // credits per 1K input tokens
    output: 6 // credits per 1K output tokens
  },
  'gpt-4o': {
    input: 25,
    output: 100
  }
  // ... more models
} as const;

Use Cases

Add a New Plan

To add a new subscription plan:

config/billing.config.ts
export const billingConfig = {
  // ... other config
  plans: {
    // ... existing plans
    business: {
      id: 'business',
      name: 'Business',
      description: 'For larger teams',
      features: [
        'Everything in Pro',
        'Advanced security',
        'Dedicated support',
        '500 GB storage'
      ],
      limits: {
        maxMembers: -1,
        maxStorage: 500
      },
      prices: [
        {
          id: 'business_monthly',
          stripePriceId: env.NEXT_PUBLIC_STRIPE_PRICE_BUSINESS_MONTHLY ?? '',
          type: 'recurring',
          interval: 'month',
          intervalCount: 1,
          amount: 9900, // $99.00
          currency: 'usd',
          seatBased: true
        }
      ]
    }
  }
};

Disable Billing

To disable billing entirely:

config/billing.config.ts
export const billingConfig = {
  enabled: false
  // ... other config
};

Add Enterprise Plan

To add an enterprise plan (contact sales):

config/billing.config.ts
export const billingConfig = {
  // ... other config
  plans: {
    // ... existing plans
    enterprise: {
      id: 'enterprise',
      name: 'Enterprise',
      description: 'For large organizations',
      isEnterprise: true,
      features: [
        'Everything in Pro',
        'Dedicated account manager',
        'Custom SLA',
        'Unlimited storage',
        'SSO / SAML'
      ],
      limits: {
        maxMembers: -1,
        maxStorage: -1
      }
    }
  }
};

Type Definitions

The configuration uses TypeScript types for type safety:

config/billing.config.ts
export type PriceConfig = {
  id: string;
  stripePriceId: string;
  amount: number;
  currency: string;
} & (
  | {
      type: 'recurring';
      interval: 'month' | 'year' | 'week' | 'day';
      intervalCount: number;
      seatBased?: boolean;
      trialDays?: number;
    }
  | {
      type: 'one_time';
    }
);

export type PlanLimits = {
  maxMembers: number; // -1 for unlimited
  maxStorage: number; // in GB, -1 for unlimited
};

export type Plan = FreePlan | PaidPlan | EnterprisePlan;

export type BillingConfig = {
  enabled: boolean;
  defaultCurrency: string;
  plans: Record<string, Plan>;
};

Using the Configuration

Import and use the configuration in your code:

lib/billing/plans.ts
import { billingConfig } from '@/config/billing.config';

export function getPlanById(planId: string) {
  return billingConfig.plans[planId];
}

export function getAllPlans() {
  return Object.values(billingConfig.plans);
}
lib/billing/credits.ts
import { creditCosts, creditPackages } from '@/config/billing.config';

export function getCreditPackageById(id: string) {
  return creditPackages.find((pkg) => pkg.id === id);
}

export function calculateCreditsForModel(
  modelId: string,
  inputTokens: number,
  outputTokens: number
) {
  const costs = creditCosts[modelId as keyof typeof creditCosts];
  const inputCost = Math.ceil((inputTokens / 1000) * costs.input);
  const outputCost = Math.ceil((outputTokens / 1000) * costs.output);
  return inputCost + outputCost;
}

Next Steps

For more information on billing, see: