This guide will walk you through the process of building a billing portal for a SaaS application using Next.js.
Billing operations will be managed through Lemon Squeezy without any redirect directly on your platform
What will you do
When integrating billing functionalities into a SaaS application, several essential aspects must be considered. It’s not merely a matter of directing customers to a checkout page and expecting seamless operations.
Outlined below are the key billing features typically required for a SaaS application:
- User interface (UI) for selecting plans
- Mechanism for fetching plan data
- listening to webhooks for subscription and your backend synchronization
- Managing plan changes
- Managing subscription cancellations, pausing, and updating payment methods
Basic Setup
install @lemonsqueezy/lemonsqueezy.js
npm i @lemonsqueezy/lemonsqueezy.js
Set up the API
-
Get your api key dude Just Go to app.lemonsqueezy.com/settings/api to create a new key and put it in your
.env
-
Now get your store id It is essential to retain the store ID during sales transactions. Lemon Squeezy API keys are associated with users rather than specific stores. If a user has access to multiple stores, API requests will retrieve data from all accessible stores.
So to fetch from specific store you will need to get your store id You can find your store ID at Settings > Stores.
-
No we need your webhook To set up webhooks, go to Settings > Webhooks in Lemon Squeezy. Create a webhook and select at minimum
subscription_created
,subscription_expired
andsubscription_updated
from the list. This will make sure you always have the latest information about every subscription in your app’s data. And for webhook secret just put some random password you wish
Now you got all your keys, put them in env
LEMONSQUEEZY_KEY=
LEMONSQUEEZY_STORE_ID=
LEMONSQUEEZY_WEBHOOK_SECRET=
create a file under utils lemon-config.ts
and paste this code
import { lemonSqueezySetup } from "@lemonsqueezy/lemonsqueezy.js";
import { env } from "../../env";
/**
* Ensures that required environment variables are set and sets up the Lemon
* Squeezy JS SDK. Throws an error if any environment variables are missing or
* if there's an error setting up the SDK.
* required environment variables:
* - LEMONSQUEEZY_KEY
* - LEMONSQUEEZY_STORE_ID
* - LEMONSQUEEZY_WEBHOOK_SECRET
*/
export function configureLemonSqueezy() {
const requiredVars = [
"LEMONSQUEEZY_KEY",
"LEMONSQUEEZY_STORE_ID",
"LEMONSQUEEZY_WEBHOOK_SECRET",
];
const missingVars = requiredVars.filter((varName) => !process.env[varName]);
if (missingVars.length > 0) {
throw new Error(
`Missing required LEMONSQUEEZY env variables: ${missingVars.join(",")}. Please, set them in your .env file.`);
}
lemonSqueezySetup({
apiKey: env.LEMONSQUEEZY_KEY,
onError: (error) => {
throw new Error(`Lemon Squeezy API error: ${error.message}`);
}
});
}