Autumn handles your billing flows, so you don’t need to build and maintain user flows like:
  • Purchasing a product
  • Inputting quantities for prepaid products
  • Upgrading, downgrading, cancelling or renewing a product’s subscription
  • Paywalling features
  • Failed payments [coming soon]
Autumn offers the components in 2 forms: React components to drop in, or customizable shadcn/ui components that can be downloaded and edited.

Pricing Table

The pricing table component displays your available products, the features available in each and any prices. You can also pass in a productDetails prop to add information to the pricing card contents. Pricing Table React
import { PricingTable } from "autumn-js/react";
shadcn/ui
npx shadcn@latest add https://ui.useautumn.com/pricing-table
This will download the pricing-table component in your /components directory, under a /autumn folder.

Usage

import { PricingTable } from "@components/autumn/pricing-table";

export const PricingTableExample = () => (
  <div>
    <PricingTable productDetails={productDetails} />
  </div>
);
The component can take in productDetails, which can be used to pass in content that can override the default contents (which are generated from your Autumn products). The example below was used to render the screenshot above. You can choose which products should be displayed, and what items each card should have. The items array can either take an object with primaryText and secondaryText properties, or a string with the featureId, which will just take the item from Autumn’s default contents.
const productDetails = [
  {
    id: "free",
    description: "A great free plan to get started with",
  },
  {
    id: "pro",
    description: "For all your extra messaging needs",
    recommendText: "Most Popular",
    price: {
      primaryText: "$10/month",
      secondaryText: "billed monthly",
    },
    items: [
      {
        featureId: "messages",
      },
      {
        primaryText: "Premium support",
        secondaryText: "Get help from our team",
      },
    ],
  },
  {
    id: "pro_annual",
  },
  {
    id: "premium",
    description: "For those of you who are really serious",
  },
  {
    id: "premium_annual",
  },
];

Scenarios

When you install pricing-table, a @/lib/autumn/pricing-table-content.tsx file is also installed. This file contains the pricing card button texts for each scenario, which you can customize how you want.
/lib/autumn/get-checkout-content.tsx
import { type Product } from "autumn-js";

export const getPricingTableContent = (product: Product) => {
  const { scenario, free_trial, properties } = product;
  const { is_one_off, has_prepaid, has_trial } = properties;

  if (has_trial) {
    return {
      buttonText: <p>Start Free Trial</p>,
    };
  }

  switch (scenario) {
    case "scheduled":
      return {
        buttonText: <p>Plan Scheduled</p>,
      };

    case "active":
      if (has_prepaid) {
        return {
          buttonText: <p>Update Plan</p>,
        };
      }

      return {
        buttonText: <p>Current Plan</p>,
      };

    case "new":
      if (is_one_off) {
        return {
          buttonText: <p>Purchase</p>,
        };
      }

      return {
        buttonText: <p>Get started</p>,
      };

    case "renew":
      return {
        buttonText: <p>Renew</p>,
      };

    case "upgrade":
      return {
        buttonText: <p>Upgrade</p>,
      };

    case "downgrade":
      return {
        buttonText: <p>Downgrade</p>,
      };

    case "cancel":
      return {
        buttonText: <p>Cancel Plan</p>,
      };

    default:
      return {
        buttonText: <p>Get Started</p>,
      };
  }
};

Checkout Dialog

The Checkout dialog will open when a customer wants to change their active product, such as when they upgrade or downgrade, to let them preview how much will be charged, and confirm the change. Product Change Dialog React
import { CheckoutDialog } from "autumn-js/react";
shadcn/ui
npx shadcn@latest add https://ui.useautumn.com/checkout-dialog
This will download the checkout-dialog component in your /components directory, under a /autumn folder.

Usage

Pass in the checkout-dialog component to the checkout() hook. This allows Autumn to automatically open the checkout dialog when they want to change their active product. The dialog will open if:
  • The customer needs to input a quantity for their purchase (ie, if the product has prepaid prices)
  • If the customer’s payment method is already on file (ie, for upgrades, downgrades or add-ons).
When the customer confirms the purchase, Autumn will attach the product to the customer.
If there are no inputs required and it’s a new customer (without an existing payment method), the customer will be redirected straight to the Stripe checkout page.
import CheckoutDialog from "@/components/autumn/checkout-dialog";
// or import { CheckoutDialog } from "autumn-js/react";
import { useCustomer } from "autumn-js/react";

const { checkout } = useCustomer();

<Button
  onClick={async () =>
    await checkout({
      productId: "pro",
      dialog: CheckoutDialog,
    })
  }
/>;

Scenarios

When you install checkout-dialog, a @/lib/autumn/checkout-content.tsx file is also installed. This file contains the dialog texts for each scenario (returned from the checkout function), which you can customize how you want.
/lib/autumn/get-checkout-content.tsx
import { CheckProductPreview } from "autumn-js";

export const getAttachContent = (preview: CheckProductPreview) => {
  const {
    scenario,
    product_name,
    recurring,
    current_product_name,
    next_cycle_at,
  } = preview;

  const nextCycleAtStr = next_cycle_at
    ? new Date(next_cycle_at).toLocaleDateString()
    : undefined;

  switch (scenario) {
    case "scheduled":
      return {
        title: <p>Scheduled product already exists</p>,
        message: <p>You already have this product scheduled to start soon.</p>,
      };

    case "active":
      return {
        title: <p>Product already active</p>,
        message: <p>You are already subscribed to this product.</p>,
      };

    case "new":
      if (recurring) {
        return {
          title: <p>Subscribe to {product_name}</p>,
          message: (
            <p>
              By clicking confirm, you will be subscribed to {product_name} and
              your card will be charged immediately.
            </p>
          ),
        };
      } else {
        return {
          title: <p>Purchase {product_name}</p>,
          message: (
            <p>
              By clicking confirm, you will purchase {product_name} and your
              card will be charged immedaitely.
            </p>
          ),
        };
      }

    case "renew":
      return {
        title: <p>Renew</p>,
        message: (
          <p>
            By clicking confirm, you will renew your subscription to{" "}
            {product_name}.
          </p>
        ),
      };

    case "upgrade":
      return {
        title: <p>Upgrade to {product_name}</p>,
        message: (
          <p>
            By clicking confirm, you will upgrade your subscription to{" "}
            {product_name} and your card will be charged immediately.
          </p>
        ),
      };

    case "downgrade":
      return {
        title: <p>Downgrade to {product_name}</p>,
        message: (
          <p>
            By clicking confirm, your current subscription to{" "}
            {current_product_name} will be cancelled and a new subscription to{" "}
            {product_name} will begin on {nextCycleAtStr}.
          </p>
        ),
      };

    case "cancel":
      return {
        title: <p>Cancel</p>,
        message: (
          <p>
            By clicking confirm, your subscription to {current_product_name}{" "}
            will end on {nextCycleAtStr}.
          </p>
        ),
      };

    default:
      return {
        title: <p>Change Subscription</p>,
        message: <p>You are about to change your subscription.</p>,
      };
  }
};

Paywall Dialog

A paywall that prompts users to upgrade to the next tier when they hit a usage limit, or don’t have access to a feature.

Install

npx shadcn@latest add https://ui.useautumn.com/paywall-dialog
Paywall Dialog This will download the paywall-dialog component in your /components directory, under a /autumn folder.

Usage

Pass in the paywall-dialog component to the check function (exported from the useCustomer hook).
import PaywallDialog from "@/components/autumn/paywall-dialog";
// or import { PaywallDialog } from "autumn-js/react";
import { useCustomer } from "autumn-js/react";

const { check } = useCustomer();

const { data, error } = await check({
  featureId: "ai-messages",
  dialog: PaywallDialog,
});
Now when you use the check() function, Autumn will automatically pass in the withPreview: true parameter. If data.allowed: false is returned for the feature, the paywall will open with the following details:
  • The feature they don’t have access to, or have run out of
  • The next product tier they should upgrade to, in order to access the feature (or an add-on if no additional tier exists)
  • A button that lets them purchase the next tier or add-on

Scenarios

When the paywall-dialog component is installed, a /lib/autumn/get-paywall-content.tsx file is also installed. This file contains the dialog texts for each scenario (depending on the available products), which you can customize how you want.
/lib/autumn/get-paywall-content.tsx
import { CheckFeaturePreview } from "autumn-js";

export const getPaywallDialogTexts = (preview: CheckFeaturePreview) => {
  const { scenario, products, feature_name } = preview;

  if (products.length == 0) {
    switch (scenario) {
      case "usage_limit":
        return {
          title: `Feature Unavailable`,
          message: `You have reached the usage limit for ${feature_name}. Please contact us to increase your limit.`,
        };
      default:
        return {
          title: "Feature Unavailable",
          message:
            "This feature is not available for your account. Please contact us to enable it.",
        };
    }
  }

  const nextProduct = products[0];

  const isAddOn = nextProduct && nextProduct.is_add_on;

  const title = nextProduct.free_trial
    ? `Start trial for ${nextProduct.name}`
    : nextProduct.is_add_on
    ? `Purchase ${nextProduct.name}`
    : `Upgrade to ${nextProduct.name}`;

  let message = "";
  if (isAddOn) {
    message = `Please purchase the ${nextProduct.name} add-on to continue using ${feature_name}.`;
  } else {
    message = `Please upgrade to the ${nextProduct.name} plan to continue using ${feature_name}.`;
  }

  switch (scenario) {
    case "usage_limit":
      return {
        title: title,
        message: `You have reached the usage limit for ${feature_name}. ${message}`,
      };
    case "feature_flag":
      return {
        title: title,
        message: `This feature is not available for your account. ${message}`,
      };
    default:
      return {
        title: "Feature Unavailable",
        message: "This feature is not available for your account.",
      };
  }
};