Skip to main content
Sabo’s pricing component is managed through a simple data array, making it easy to customize. It includes a monthly/yearly toggle, Stripe checkout integration, and special handling for free and enterprise plans. This guide explains how to customize the pricing plans, adjust UI elements, and connect the buttons to your Stripe account.

File Locations

  • Main Component: src/components/marketing/pricing.tsx (Handles all logic and UI)
  • Page Route: src/app/(marketing)/pricing/page.tsx (Renders the component and other sections)

How to Customize Pricing Plans

All pricing plans are managed in the plans array at the top of the file. By modifying the objects in this array, you can change the content of each pricing card.

Understanding the plans Array

Each object in the array represents a single pricing card and has the following properties, in order:
name
string
The name of the plan (e.g., “Pro”, “Enterprise”).
monthlyPrice
number | null
The price per month to display on the UI. Set to null for plans without a fixed price (like Enterprise).
yearlyPrice
number | null
The price per month when billed annually to display on the UI. Set to null for plans without a fixed price.
monthlyPriceId
string | null
The Stripe Price ID for the monthly subscription. This is sent to your backend for checkout. Set to null for non-purchasable plans (like Free or Enterprise).
yearlyPriceId
string | null
The Stripe Price ID for the yearly subscription. Set to null for non-purchasable plans.
description
string
A short description of the plan shown below the price.
include
string
A short text displayed above the features list (e.g., “Everything in Pro +”).
features
string[]
An array of strings, where each string is a feature listed on the card.
If true, a “Popular” badge is displayed on the card, and the button uses the primary color.
buttonText
string
The text displayed on the main call-to-action button.
isFree
boolean
Set to true for the free plan. This makes the button redirect to the sign-up page instead of initiating a Stripe checkout.
isContactUs
boolean
Set to true for enterprise-style plans. This displays the price as “Custom” and makes the button open an email client to contact sales.

Example: Modifying a Plan

To change a plan, simply find its object in the plans array and edit the properties.
src/components/marketing/pricing.tsx
const plans = [
  // ...
  {
    name: "Pro", // Renamed from "Startup"
    monthlyPrice: 25,
    yearlyPrice: 20,
    monthlyPriceId: "price_your_pro_monthly_id", // Your Stripe Price ID
    yearlyPriceId: "price_your_pro_yearly_id",   // Your Stripe Price ID
    description: "Perfect for power users and growing teams.",
    features: [
      "All features from the previous plan",
      "Advanced analytics",
      "Priority support",
      // ... add more features
    ],
    isPopular: true,
    buttonText: "Go Pro",
  },
  // ...
];

Connecting Buttons to Stripe

This section focuses on connecting buttons for recurring subscriptions. For a full guide on backend setup (APIs, webhooks) and implementing one-time payments, please see the main Payments with Stripe documentation.
1

Store your Price IDs in .env.local

It is highly recommended to store your Price IDs in an environment file (.env.local) with the NEXT_PUBLIC_ prefix. This keeps your configuration separate from your code.
.env.local
NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID=price_xxxxxxxxxxxxxx
NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID=price_yyyyyyyyyyyyyy
2

Connect Price IDs in the Component

In pricing.tsx, use process.env to assign these IDs to the plans array.
src/components/marketing/pricing.tsx
// ...
const plans = [
  {
    name: "Pro",
    // ...
    monthlyPriceId: process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID,
    yearlyPriceId: process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID,
    // ...
  },
];
// ...
When a user clicks a purchase button, the handleSubmit function runs the following logic:
  1. Checks for special plans: It first checks if the plan is “Free” or “Contact Us” and handles them separately (e.g., redirecting to sign-up or opening an email client).
  2. Checks user authentication: For paid plans, it uses Supabase to check if the user is logged in.
    • If the user is not logged in, they are redirected to the /sign-in page. After signing in, they will be returned to the pricing page to complete the purchase.
    • If the user is logged in, it proceeds to the next step.
  3. Initiates checkout: It sends the selected price_id to the /api/checkout_sessions API route, which then redirects the user to a Stripe Checkout page to complete the payment.

Customizing UI Elements

1

Billing Cycle Toggle

The discount badge for the yearly plan can be customized directly in the JSX. You can change the discount percentage or the text.
src/components/marketing/pricing.tsx
// ...
<span className="ml-2 ...">
  -20% {/* Change discount text here */}
</span>
// ...
2

`Contact Sales` Email

For the Enterprise plan, the “Contact Sales” button opens a mailto: link. You can change the recipient email and subject line inside the handleSubmit function.
src/components/marketing/pricing.tsx
// ...
if (isContactUs) {
  window.open(
    "mailto:[email protected]?subject=Enterprise Inquiry", // Edit this line
    "_self"
  );
  return;
}
// ...