🔄 Subscriptions Module

Complete subscription management with pricing plans, subscription lifecycle, and recurring billing.

✨ Features
Billing

Recurring Billing

Automated subscription billing with Stripe

Plans

Pricing Plans

Flexible pricing configuration system

Lifecycle

Subscription Lifecycle

Complete subscription management and status tracking

Portal

Customer Portal

Self-service subscription management

Components

UI Components

Pricing cards and subscription manager

Webhooks

Event Handling

Subscription event processing and notifications

🚀 Installation
npx shadcn@latest add "https://supremetoolkit.in/r/subscriptions"

This installs:

  • • Stripe subscription configuration and client setup
  • • PricingCard and SubscriptionManager components
  • • Pricing configuration system with plans
  • • useSubscription and useCustomerPortal hooks
  • • Server actions for subscription events
  • • API routes for subscription management
  • • Required dependencies (stripe, @stripe/stripe-js)
🔧 Environment Variables & Setup

Stripe Account Required

You need a Stripe account with subscription products configured. Sign up at stripe.com and set up your subscription products.

1. Add Stripe API Keys:

# .env.local
# Required - Get these from your Stripe Dashboard
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here

# Required for webhooks (essential for subscriptions)
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here

2. Create Subscription Products in Stripe:

• Go to Stripe Dashboard → Products

• Create products with recurring pricing (monthly/yearly)

• Copy the price IDs (starts with 'price_')

• Note: Use price IDs, not product IDs for subscriptions

3. Configure Pricing in lib/pricing.ts:

export const pricingPlans = [
  {
    id: 'starter',
    name: 'Starter',
    price: 9,
    interval: 'month',
    stripePriceId: 'price_your_starter_monthly_price_id',
    features: ['Feature 1', 'Feature 2'],
  },
  {
    id: 'pro',
    name: 'Pro',
    price: 29,
    interval: 'month',
    stripePriceId: 'price_your_pro_monthly_price_id',
    features: ['All Starter features', 'Feature 3', 'Feature 4'],
  },
];

4. Set up Webhooks (Required for Subscriptions):

• Go to Stripe Dashboard → Webhooks

• Add endpoint: https://yourdomain.com/api/stripe/webhooks

• Select events:

  • - customer.subscription.created
  • - customer.subscription.updated
  • - customer.subscription.deleted
  • - invoice.payment_succeeded
  • - invoice.payment_failed

• Copy the webhook signing secret to your .env.local file

Webhooks Are Essential

Unlike one-time payments, subscriptions require webhooks to handle recurring billing, failed payments, and subscription status changes. Make sure to set up webhooks before going live.

📦 What's Included

PricingCard

Beautiful pricing cards with integrated subscription functionality

<PricingCard plan={plan} onSubscribe={handleSubscribe} />

SubscriptionManager

Complete subscription management interface

<SubscriptionManager subscription={userSub} />

PricingGrid

Grid layout for multiple pricing plans

<PricingGrid plans={plans} columns={3} />
⚙️ Configuration

Environment Variables:

# .env.local
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here

# Optional: Configure in config.tsx
NEXT_PUBLIC_APP_URL=https://yourapp.com

Pricing Plans Configuration:

// lib/pricing.ts - Customize your pricing plans

export const defaultPricingPlans: PricingPlan[] = [
  {
    id: 'starter',
    name: 'Starter',
    description: 'Perfect for individuals getting started',
    price: 9.99,
    currency: 'USD',
    interval: 'month',
    stripeProductId: 'prod_starter',
    stripePriceId: 'price_your_stripe_price_id',
    features: [
      { name: 'Up to 5 projects', included: true },
      { name: 'Basic support', included: true },
      { name: 'Advanced features', included: false },
    ],
  },
  // Add more plans...
];
🔧 Usage Examples

Simple pricing page:

import { PricingCard, PricingGrid } from '@/components/ui/pricing-card';
import { getPricingPlans } from '@/lib/pricing';

export default function PricingPage() {
  const monthlyPlans = getPricingPlans('month');
  const yearlyPlans = getPricingPlans('year');
  const [billingInterval, setBillingInterval] = useState('month');

  const currentPlans = billingInterval === 'month' ? monthlyPlans : yearlyPlans;

  return (
    <div className="max-w-6xl mx-auto p-6">
      <div className="text-center mb-8">
        <h1 className="text-3xl font-bold">Choose Your Plan</h1>
        <p className="text-muted-foreground">Select the perfect plan for your needs</p>

        {/* Billing toggle */}
        <div className="flex items-center justify-center mt-4">
          <button
            onClick={() => setBillingInterval('month')}
            className={`px-4 py-2 ${billingInterval === 'month' ? 'bg-blue-600 text-white' : 'bg-gray-200'}`}
          >
            Monthly
          </button>
          <button
            onClick={() => setBillingInterval('year')}
            className={`px-4 py-2 ${billingInterval === 'year' ? 'bg-blue-600 text-white' : 'bg-gray-200'}`}
          >
            Yearly (Save 20%)
          </button>
        </div>
      </div>

      <PricingGrid
        plans={currentPlans}
        columns={3}
        onSubscribe={(plan) => {
          console.log('Subscribing to:', plan.name);
        }}
      />
    </div>
  );
}

Custom subscription checkout:

import { useCheckout } from '@/hooks/use-stripe';
import { useState } from 'react';

export default function SubscriptionCheckout() {
  const [selectedPlan, setSelectedPlan] = useState('pro-monthly');
  const { redirectToCheckout, loading, error } = useCheckout();

  const plans = {
    'starter-monthly': { priceId: 'price_starter_monthly', name: 'Starter Monthly' },
    'pro-monthly': { priceId: 'price_pro_monthly', name: 'Pro Monthly' },
    'enterprise-monthly': { priceId: 'price_enterprise_monthly', name: 'Enterprise Monthly' },
  };

  const handleSubscribe = async () => {
    const plan = plans[selectedPlan];

    try {
      await redirectToCheckout({
        priceId: plan.priceId,
        mode: 'subscription',
        successUrl: '/dashboard?subscription=success',
        cancelUrl: '/pricing',
        metadata: {
          plan: selectedPlan,
          source: 'pricing-page'
        }
      });
    } catch (err) {
      console.error('Subscription failed:', err);
    }
  };

  return (
    <div className="max-w-md mx-auto">
      <h2>Subscribe to {plans[selectedPlan].name}</h2>

      <div className="space-y-2 mb-4">
        {Object.entries(plans).map(([key, plan]) => (
          <label key={key} className="flex items-center space-x-2">
            <input
              type="radio"
              value={key}
              checked={selectedPlan === key}
              onChange={(e) => setSelectedPlan(e.target.value)}
            />
            <span>{plan.name}</span>
          </label>
        ))}
      </div>

      {error && (
        <div className="text-red-500 mb-4">
          Error: {error}
        </div>
      )}

      <button
        onClick={handleSubscribe}
        disabled={loading}
        className="w-full bg-blue-600 text-white py-2 px-4 rounded disabled:opacity-50"
      >
        {loading ? 'Processing...' : 'Subscribe Now'}
      </button>
    </div>
  );
}
🌟 Best Practices

Pricing Strategy

Offer annual discounts (typically 15-20%) to improve customer lifetime value and reduce churn.

Trial Periods

Consider offering free trials to reduce friction and let users experience value before committing.

Webhook Reliability

Implement idempotent webhook handlers and proper retry logic to handle webhook delivery failures.

Customer Experience

Provide clear billing information, easy cancellation, and proactive communication about subscription changes.

Dunning Management

Implement smart retry logic for failed payments and communicate with customers about payment issues.

Analytics & Metrics

Track key metrics like MRR, churn rate, LTV, and conversion rates to optimize your subscription business.