v1
Billing & Subscriptions

Billing & subscriptions with Stripe

Subscriptions are a way to allow your customers to pay for access to your app or certain features of it. Subscriptions in supastarter are managed by Stripe, and you can use the Stripe (opens in a new tab) dashboard to manage your plans.

1. Setup stripe

To setup stripe, you need to create an account on Stripe (opens in a new tab) and get your API keys.

After you have signed to to Stripe head to the API keys (opens in a new tab) page and copy your publishable key and secret key.

Then, you need to add your API keys to your .env file into the following variables:

NEXT_PUBLIC_STRIPE_PUBLIC_KEY=<YOUR_STRIPE_PUBLISHABLE_KEY>
STRIPE_SECRET_KEY=<YOUR_STRIPE_SECRET_KEY>

Stripe api keys


2. Setup stripe webhook

Stripe uses webhooks to notify your app when a data changes, for example when a product, price or subscription is created, updated or deleted. This way you can keep your data in sync with Stripe. supastarter sync the data to your database to make sure the data loads fast and your don't run into problems of rate limits of the Stripe API. Make sure you do these steps before any other steps, so your Stripe data is properly synced.

To create a webhook, head to the webhooks (opens in a new tab) page and click on the Add endpoint button.

Stripe webhooks

Enter the endpoint URL for your webhook. It will be the deployment URL of your app with /api/stripe-webhook appended to it. For example, if your app is deployed to https://my-app.co, the endpoint URL will be https://my-app.co/api/stripe-webhook.

Then click Select events and select the following events:

Price

  • 'price.created'
  • 'price.updated'
  • 'price.deleted'

Product

  • 'product.created'
  • 'product.updated'
  • 'product.deleted'

Checkout

  • 'checkout.session.completed'

Customer

  • 'customer.subscription.created'
  • 'customer.subscription.updated'
  • 'customer.subscription.deleted'

After hitting the Add endpoint button, you will be redirected to the webhook page. Copy the signing secret (it should start with _whsec__) and add it to your .env file into the following variable:

STRIPE_WEBHOOK_SECRET=<YOUR_STRIPE_WEBHOOK_SECRET>

3. Setup your plans

Make sure you have setup Stripe and Stripe webhook before you continue. If you don't have a deployed version of your app yet, you can proxy the Stripe webhook to your local instance.

To setup your plans, you need to create them on the Stripe dashboard (opens in a new tab).

supastarter enables you to offer multiple plans for your app (billed in different intervals) and you can even offer them in different currencies.

All you need to do is to create a product for each plan and then add prices to it. For example, if you want to offer a monthly and an annual plan, you need to create one product and then add two prices to each product. If you want to offer the same plan in different currencies, you need to add a price for each currency and each interval.

For the example plans in the supastarter app, we have created three plans/products: Basic, Pro and Ultimate. Each plan has two prices: one for monthly and one for annual billing. All plans are available in USD and EUR.

Stripe products

To create the plans, head to the products (opens in a new tab) page and click on the Create product button.

Enter a name for your product and create the prices you would like to offer. You can leave out the description, since we will create a translatable description for each plan in the next step. Then click on the Create button.

Create a product on stripe

Your product will be created and synced to your database. To make sure the data is synced, take a look at your products and prices table in your database in Supabase under Table Editor.

Supabase products table


4. Setup your plans in your app

Now it's time to setup the plans in your app, so they are available to your customers.

First we are going to create an enum for the plans. This way we can use the enum in our code instead of the product id and we don't have to worry about typos.

The values of the enum are the product ids from Stripe. You can find them on the products (opens in a new tab) page on the right top corner.

Find product id in Stripe

Open the config/subscriptions.ts file and change the enum according to your plans:

export enum SubscriptionPlanId {
  Basic = 'prod_MjlslP8ZhJE2BT',
  Pro = 'prod_MkEcaiAquWT5Mw',
  Ultimate = 'prod_MkEdajGmU78KZh',
}

You can also set a recommended plan for your app. This plan will be highlighted in the pricing table as you can see in the example image below.

export const recommendedPlanId = SubscriptionPlanId.Basic;

Next we are going to create a translatable title, description and feature list for each plan. Open the lib/client/subscriptions.ts file. In the useSubscriptionPlans hook, you will find a variable called translations:

const translations: Record<string, { name?: string; description?: string; features?: string[] }> = {
  [SubscriptionPlanId.Basic]: {
    name: t('subscriptionPlans.basic.name'),
    description: t('subscriptionPlans.basic.description'),
    features: [
      t('subscriptionPlans.basic.features.0'),
      t('subscriptionPlans.basic.features.1'),
      t('subscriptionPlans.basic.features.2'),
    ],
  },
  [SubscriptionPlanId.Pro]: {
    name: t('subscriptionPlans.pro.name'),
    description: t('subscriptionPlans.pro.description'),
    features: [
      t('subscriptionPlans.pro.features.0'),
      t('subscriptionPlans.pro.features.1'),
      t('subscriptionPlans.pro.features.2'),
    ],
  },
  [SubscriptionPlanId.Ultimate]: {
    name: t('subscriptionPlans.ultimate.name'),
    description: t('subscriptionPlans.ultimate.description'),
    features: [
      t('subscriptionPlans.ultimate.features.0'),
      t('subscriptionPlans.ultimate.features.1'),
      t('subscriptionPlans.ultimate.features.2'),
    ],
  },
};

Add your plans to the translations object. You can use the t function to translate the title, description and feature list. To learn more about how to translate your app, check out the internationalization documentation.

Now you should be able to see the plans in your app in the pricing section on the landing page:

Pricing section


5. Customize Stripe checkout and customer portal

To make sure your customers have a great experience when they subscribe to your app, you can customize the Stripe checkout and customer portal match to your brand design. To do so, head into the Branding settings (opens in a new tab) in the Stripe admin dashboard. Here you will find controls to customize the colors and logo of the receipts, the checkout, the customer portal and and more.

Supabase products table


Bonus: Run webhook on your local machine

If you don't have a deployed version of your app yet, you can run the webhook on your local machine. To do this, you will need the Stripe CLI. Follow the instructions (opens in a new tab) to install it.

After you have installed the Stripe CLI, run the following command to start the webhook:

stripe listen --forward-to localhost:3000/api/stripe-webhook

This will redirect the webhook to your localhost. This way you can sync your Stripe data to your database without having to deploy your app.

To learn more about testing Stripe webhooks, check out the Stripe docs (opens in a new tab).