> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getsabo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pricing

> Learn how to customize the pricing page, including the plans, features, and Stripe integration.

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:

<ParamField path="name" type="string">
  The name of the plan (e.g., "Pro", "Enterprise").
</ParamField>

<ParamField path="monthlyPrice" type="number | null">
  The price per month to display on the UI. Set to `null` for plans without a fixed price (like Enterprise).
</ParamField>

<ParamField path="yearlyPrice" type="number | null">
  The price per month *when billed annually* to display on the UI. Set to `null` for plans without a fixed price.
</ParamField>

<ParamField path="monthlyPriceId" type="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).
</ParamField>

<ParamField path="yearlyPriceId" type="string | null">
  The **Stripe Price ID** for the yearly subscription. Set to `null` for non-purchasable plans.
</ParamField>

<ParamField path="description" type="string">
  A short description of the plan shown below the price.
</ParamField>

<ParamField path="include" type="string">
  A short text displayed above the features list (e.g., "Everything in Pro +").
</ParamField>

<ParamField path="features" type="string[]">
  An array of strings, where each string is a feature listed on the card.
</ParamField>

<ParamField path="isPopular" type="boolean">
  If `true`, a "Popular" badge is displayed on the card, and the button uses the primary color.
</ParamField>

<ParamField path="buttonText" type="string">
  The text displayed on the main call-to-action button.
</ParamField>

<ParamField path="isFree" type="boolean">
  Set to `true` for the free plan. This makes the button redirect to the sign-up page instead of initiating a Stripe checkout.
</ParamField>

<ParamField path="isContactUs" type="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.
</ParamField>

#### Example: Modifying a Plan

To change a plan, simply find its object in the `plans` array and edit the properties.

```tsx src/components/marketing/pricing.tsx theme={null}
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

<Note>
  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](/core-features/payments-with-stripe).
</Note>

<Steps>
  <Step title="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.

    ```bash .env.local theme={null}
    NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID=price_xxxxxxxxxxxxxx
    NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID=price_yyyyyyyyyyyyyy
    ```
  </Step>

  <Step title="Connect Price IDs in the Component">
    In `pricing.tsx`, use `process.env` to assign these IDs to the `plans` array.

    ```tsx src/components/marketing/pricing.tsx theme={null}
    // ...
    const plans = [
      {
        name: "Pro",
        // ...
        monthlyPriceId: process.env.NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID,
        yearlyPriceId: process.env.NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID,
        // ...
      },
    ];
    // ...
    ```

    <Accordion title="How the submission logic works">
      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.

      <details>
        <summary>View the `handleSubmit` function code</summary>

        ```tsx src/components/marketing/pricing.tsx theme={null}
        // ...
        const handleSubmit = async (
          e: React.FormEvent<HTMLFormElement>,
          priceId: string | undefined,
          isContactUs?: boolean,
          isFree?: boolean
        ) => {
          e.preventDefault();

          // Handle Contact Us button
          if (isContactUs) {
            window.open("mailto:sales@example.com?subject=Enterprise Plan Inquiry", "_self");
            return;
          }

          // Handle Free plan - redirect to sign up
          if (isFree) {
            router.push("/sign-up");
            return;
          }

          // ... (rest of the function)
        }
        ```
      </details>
    </Accordion>
  </Step>
</Steps>

## Customizing UI Elements

<Steps>
  <Step title="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.

    ```tsx src/components/marketing/pricing.tsx theme={null}
    // ...
    <span className="ml-2 ...">
      -20% {/* Change discount text here */}
    </span>
    // ...
    ```
  </Step>

  <Step title="`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.

    ```tsx src/components/marketing/pricing.tsx theme={null}
    // ...
    if (isContactUs) {
      window.open(
        "mailto:your-sales-email@example.com?subject=Enterprise Inquiry", // Edit this line
        "_self"
      );
      return;
    }
    // ...
    ```
  </Step>
</Steps>
