Configuring Stripe Billing in the React Router Supabase SaaS Kit
Learn how to configure Stripe in the Makerkit React Router Supabase SaaS Kit
Stripe is the default billing provider in both the local config and the DB, so you don't need to set these values if you want to use Stripe.
For Stripe, you'll need to set the following environment variables:
STRIPE_SECRET_KEY=STRIPE_WEBHOOK_SECRET=VITE_STRIPE_PUBLISHABLE_KEY=While the VITE_STRIPE_PUBLISHABLE_KEY is public and can be added anywhere - please do not add the secret keys to the .env file.
During development, you can place them in .env.local as it's not committed to the repository. In production, you can set them in the environment variables of your hosting provider.
Stripe CLI
The Stripe CLI which allows you to listen to Stripe events straight to your own localhost. You can install and use the CLI using a variety of methods, but we recommend using Docker - since you already have it installed.
First - login to your Stripe account using the project you want to run:
docker run --rm -it --name=stripe -v ~/.config/stripe:/root/.config/stripe stripe/stripe-cli:latest loginNow, you can listen to Stripe events running the following command:
pnpm run stripe:listenIf you have not logged in - the first time you set it up, you are required to sign in. This is a one-time process. Once you sign in, you can use the CLI to listen to Stripe events.
Please sign in and then re-run the command. Now, you can listen to Stripe events.
Linux Troubleshooting
Some users reported not being able to run Stripe using the provided command. If you encounter this issue, you can try to change the command to the following:
packages/billing/stripe/package.json
docker run --rm -it --name=stripe -v ~/.config/stripe:/root/.config/stripe stripe/stripe-cli:latest listen --network=host --forward-to http://localhost:3000/api/billing/webhookAlternatively, please install the Stripe CLI globally on your machine and run the following command instead of using Docker. You will then be able to run the command stripe listen instead of using Docker. You can find more information about the Stripe CLI here.
Adding the environment variables
Once you start listening to Stripe events, you can use the CLI to listen to Stripe events.
Now, please copy the webhook secret displayed in the terminal and set it as the STRIPE_WEBHOOK_SECRET environment variable in your .env.local file:
STRIPE_WEBHOOK_SECRET=*your_webhook_secret*If you're not receiving events, please make sure that:
- the webhook secret is correct
- the account you signed in is the same as the one you're using in your app
Configuring the Stripe Customer Portal
Stripe requires you to set up the Customer Portal so that users can manage their billing information, invoices and plan settings from there.

- Please make sure to enable the setting that lets users switch plans
- Configure the behavior of the cancellation according to your needs
Setting Production Webhooks in Stripe
When going to production, you will need to set the webhook URL and the events you want to listen to in Stripe.
The webhook path is /api/billing/webhook. If your app is hosted at https://myapp.com then you need to enter https://myapp.com/api/billing/webhook.
Use a public URL
Please make sure to use a public URL for your webhooks. If you use a private URL (such as Vercel preview URLs), you will not be able to receive webhooks from Stripe.
To ensure the URL is publicly accessible, please visit it using Incognito mode in your browser.
Makerkit needs the following events to work:
checkout.session.completedcustomer.subscription.updatedcustomer.subscription.deleted
Only if you're using one-off payments, please add:
checkout.session.async_payment_failedcheckout.session.async_payment_succeeded
If your application needs more events, please add them, but remember to handle them.
You can handle additional events by adding the required handlers in the apps/web/app/routes/api/billing/webhook.ts file.
Handling subscriptions if migrating to Makerkit
If you are migrating to Makerkit and have existing subscriptions, you need to handle them properly. The kit expects the subscriptions to have the following metadata:
{ "accountId": "123"}It's very unlikely that you have this metadata set, so you have two options:
- Add the metadata to the existing subscriptions (requires manual intervention or a migration script)
- Change how you detect the account ID from the subscription
const accountId = subscription.metadata.accountId as string;The alternative is to change how you detect the account ID from the subscription. Instead of using the metadata, you can use the customer ID to detect the account ID by querying it in the database when a subscription is updated.