What you’re setting up
Four things to make LemonSqueezy work:- Products and variants in LemonSqueezy
- Checkout URLs for your app buttons
- A webhook endpoint
- A variant-to-purchase-type mapping
Env vars
Setup
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.
Create your checkout links
Create hosted checkout links for each product you want to sell, then paste them into
.env.local:Map variants to purchase types
The repo resolves LemonSqueezy purchases by variant ID. Tell it what each variant means:This is how your app knows that variant
123456 is a medium plan purchase and variant 123457 is a small credits pack.How it works under the hood
Once LemonSqueezy sends a paid order webhook:- The repo verifies the webhook signature
- It reads the variant ID from the event
- It maps that variant to a purchase type via
LEMON_SQUEEZY_VARIANT_MAP - It stores the purchase in the database
- 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
purchasestable - Credits or plan state update correctly
Created the product but nothing shows in the app
Created the product but nothing shows in the app
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.Webhook verification fails
Webhook verification fails
Double-check that
LEMON_SQUEEZY_WEBHOOK_SECRET matches what’s in your LemonSqueezy webhook settings. A typo or stale value will cause silent failures.Payment succeeds but purchase type is wrong
Payment succeeds but purchase type is wrong
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.Works locally but not in production (or vice versa)
Works locally but not in production (or vice versa)
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.

