Configuration
Configure billing for your application.
The billing configuration schema replicates your billing provider's schema, so that:
- we can display the data in the UI (pricing table, billing section, etc.)
- create the correct checkout session
- make some features work correctly - such as feature-based access
It is common to all billing providers and placed in packages/billing/src/config/index.ts
. Some billing providers have some differences in what you can or cannot do. In these cases, the schema will try to validate and enforce the rules - but it's up to you to make sure the data is correct.
The schema is based on few entities:
- Plans: The main product you are selling (e.g., "Pro Plan", "Starter Plan", etc.)
- Prices: The pricing plan for the product (e.g., "Monthly", "Yearly", etc.)
- Discounts: The discount for the price (e.g., "10% off", "20% off", etc.)
Getting the schema right is important!
Getting the IDs of your plans is extremely important - as these are used to:
- create the correct checkout
- manage your customers billing data
Please take it easy while you configure this, do one step at a time, and test it thoroughly.
Billing provider
To set the billing provider, you need to modify the BILLING_PROVIDER
environment variable. It defaults to Stripe.
It's important to set it correctly, as this is used to determine the correct API calls and environment variables used during the communication with the billing provider.
Billing model
To set the billing model, you need to modify the BILLING_MODEL
environment variable. It defaults to recurring
as it's the most common model for SaaS apps.
This field will be used to display corresponding data in the UI (e.g. in pricing tables) and to create the correct checkout session.
Available billing models
For now, TurboStarter supports two billing models:
recurring
- for subscription-based modelsone-time
- for one-time payments
When changing it, make sure to also update corresponding data on the provider side to match it with the correct billing model.
Currency
To set the currency, you need to modify the currency
field. It defaults to usd
as it's the most common currency around the world.
Mae sure to have the same currency set on your third-party billing provider (e.g. as a store currency on Lemon Squeezy)
Plans
Plans are the main products you are selling. They are defined by the following fields:
Let's break down the fields:
id
: The unique identifier for the plan. This is chosen by you, it doesn't need to be the same one as the one in the provider.name
: The name of the plandescription
: The description of the plantype
: The type of the plan (e.g.,free
,pro
,enterprise
, etc.). It's used to determine the access level of the plan.badge
: A badge to display on the product (e.g., "Bestseller", "Popular", etc.)
The majority of these fields are going to populate the pricing table in the UI.
Prices
Prices are the pricing plans for the plan. They are defined by the following fields:
Let's break down the fields:
id
: The unique identifier for the price. This must match the price ID in the billing provideramount
: The amount of the price (displayed values will be divided by 100)interval
: The interval of the price (e.g.,month
,year
, etc.)trialDays
: The number of trial days for the pricetype
: The type of the price (e.g.,recurring
,one-time
, etc.)
The amount is set for UI purposes. The billing provider will handle the actual billing - therefore, please make sure the amount is correctly set in the billing provider.
Set the correct price ID!
Make sure to set the correct price ID that corresponds to the price in the billing provider. This is very important - as this is used to identify the correct price when creating a checkout session.
One-off payments
One-off payments are a type of price that is used to create a checkout session for a one-time payment. They are defined by the following fields:
Let's break down the fields:
id
: The unique identifier for the price. This must match the price ID in the billing provideramount
: The amount of the price (displayed values will be divided by 100)type
: The type of the price (e.g.recurring
,one-time
, etc.). In this case it'sone-time
as it's a one-off payment.
Please remember that the cost is set for UI purposes. The billing provider will handle the actual billing - therefore, please make sure the cost is correctly set in the billing provider.
Custom prices
Sometimes - you want to display a price in the pricing table - but not actually have it in the billing provider. This is common for custom plans, free plans that don't require the billing provider subscription, or plans that are not yet available.
To do so, let's add the custom
flag to the price:
Here's the full example:
As you can see, the plan is now a custom plan. The UI will display the plan in the pricing table, but it won't be available for purchase.
We do this by adding the following fields:
custom
: A flag to indicate that the plan is custom. This will prevent the plan from being available for purchase. It's set tofalse
by default.label
: This is used to display the label in the pricing table instead of the price.href
: The link to the page where the user can contact you. This is used in the pricing table.
Discounts
Sometimes, you want to offer a discount to your users. This is done by adding a discount to the price in discounts
field.
Let's break down the fields:
code
: The code of the discount (e.g., "50OFF", "10% off", etc.) This must match the code configured in the billing providertype
: The type of the discount (e.g.,percent
,amount
, etc.)off
: The amount of the discount (e.g., 50 for 50% off)appliesTo
: The list of prices that the discount applies to. This is the price ID that you've configured above for the price.
This data will allow to display the correct banner in the UI e.g. "10% off for the first 100 customers!" and to apply the discount to the correct price at checkout.
Adding more products, plans and discounts
Simply add more plans, prices and discounts to the arrays. The UI should be able to handle it in most traditional cases. If you have a more complex billing schema, you may need to adjust the UI accordingly.
Last updated on