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:

  1. User interface (UI) for selecting plans
  2. Mechanism for fetching plan data
  3. listening to webhooks for subscription and your backend synchronization
  4. Managing plan changes
  5. Managing subscription cancellations, pausing, and updating payment methods

Basic Setup

install @lemonsqueezy/lemonsqueezy.js

npm i @lemonsqueezy/lemonsqueezy.js

Set up the API

  1. Get your api key dude Just Go to app.lemonsqueezy.com/settings/api to create a new key and put it in your .env

  2. 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.

  3. 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 and subscription_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}`);
}
});
 
}