Skip to main content
LemonSqueezy is often the easiest path to accepting payments — it’s super product/variant oriented out of the box, which means less configuration for you. Let’s get it running.

What you’re setting up

Four things to make LemonSqueezy work:
  1. Products and variants in LemonSqueezy
  2. Checkout URLs for your app buttons
  3. A webhook endpoint
  4. A variant-to-purchase-type mapping

Env vars

NEXT_PUBLIC_PAYMENT_PROVIDER=lemonsqueezy
NEXT_PUBLIC_CHECKOUT_URL_TEMPLATE=https://...
LEMON_SQUEEZY_WEBHOOK_SECRET=...

Setup

1

Create your products and variants

Head to your LemonSqueezy dashboard and create the products you want to sell.Create variants if needed, and decide which ones represent:
  • Small / Medium / Large plans
  • Small / Large credit packs
In LemonSqueezy, the variant ID is the important identifier this repo uses to map purchases. Keep track of those IDs.
2

Create your checkout links

Create hosted checkout links for each product you want to sell, then paste them into .env.local:
NEXT_PUBLIC_CHECKOUT_URL_PLAN_MEDIUM=https://yourstore.lemonsqueezy.com/buy/...
NEXT_PUBLIC_CHECKOUT_URL_CREDITS_SMALL=https://yourstore.lemonsqueezy.com/buy/...
3

Map variants to purchase types

The repo resolves LemonSqueezy purchases by variant ID. Tell it what each variant means:
LEMON_SQUEEZY_VARIANT_MAP='{"123456":"plan-medium","123457":"credits-small"}'
This is how your app knows that variant 123456 is a medium plan purchase and variant 123457 is a small credits pack.
4

Add the webhook

In your LemonSqueezy webhook settings, add this endpoint:
https://yourdomain.com/api/payments/lemonsqueezy
Then copy the webhook secret into your env:
LEMON_SQUEEZY_WEBHOOK_SECRET=...
Without the webhook configured, payments succeed in LemonSqueezy but your app will never know about them. Credits won’t be added and purchases won’t be stored.

How it works under the hood

Once LemonSqueezy sends a paid order webhook:
  1. The repo verifies the webhook signature
  2. It reads the variant ID from the event
  3. It maps that variant to a purchase type via LEMON_SQUEEZY_VARIANT_MAP
  4. It stores the purchase in the database
  5. It updates credits or purchase state
If the variant ID is unknown (not in your map), the purchase is safely ignored rather than applying the wrong result. No data gets corrupted.

Verify your setup

Your LemonSqueezy setup is working if all of these are true:
  • The app opens the LemonSqueezy checkout page
  • LemonSqueezy shows a successful webhook delivery
  • A row appears in your purchases table
  • Credits or plan state update correctly
You probably created the product in LemonSqueezy but forgot to save the checkout URL in your .env.local file. The app needs those URLs to build payment buttons.
Double-check that LEMON_SQUEEZY_WEBHOOK_SECRET matches what’s in your LemonSqueezy webhook settings. A typo or stale value will cause silent failures.
Check that the variant ID in LEMON_SQUEEZY_VARIANT_MAP matches the actual variant ID from LemonSqueezy. You can find this in the product settings.
Make sure your webhook URL points to the right environment. If you’re testing locally, it should point to your local tunnel. In production, it should point to your production domain.

Payments Overview

Go back to the shared payment architecture and basics.