Leave Localhost logoLeave LocalhostDocs
Billing

Lemon Squeezy

Leave Localhost supports Lemon Squeezy as a billing provider.

Leave Localhost supports Lemon Squeezy as a billing provider.

Setup

  1. Select Lemon Squeezy as the active provider:

    BILLING_PROVIDER=lemon_squeezy

    All provider integrations are compiled into the deployment; BILLING_PROVIDER alone decides which one is active. Lemon Squeezy needs no extra dependency — webhooks are verified with the Web Crypto API. Leaving BILLING_PROVIDER blank disables billing regardless of the other variables.

  2. Set environment variables in your Convex deployment:

    BILLING_PROVIDER=lemon_squeezy
    LEMON_SQUEEZY_API_KEY=...
    LEMON_SQUEEZY_STORE_ID=...
    LEMON_SQUEEZY_WEBHOOK_SECRET=...
    LEMON_SQUEEZY_TEST_MODE=true    # or "false" for production
    LEMON_SQUEEZY_PRO_MONTHLY_VARIANT_ID=...
    LEMON_SQUEEZY_PRO_YEARLY_VARIANT_ID=...
    LEMON_SQUEEZY_PRO_LIFETIME_VARIANT_ID=...
  3. Create products and variants in the Lemon Squeezy dashboard:

    • A product with a monthly subscription variant
    • A product with a yearly subscription variant
    • A product with a one-time payment variant (for lifetime)
  4. Set up the webhook in the Lemon Squeezy dashboard:

    • URL: https://<your-convex-url>/webhooks/lemon-squeezy
    • Subscribe to subscription and order events

How It Works

The Lemon Squeezy adapter at billing/lemonSqueezy/adapter.ts implements the BillingProviderAdapter interface:

  • createCheckout — creates a checkout via the Lemon Squeezy API with the mapped variant ID.
  • createCustomerPortal — redirects to the customer portal.
  • cancelCurrentSubscription — cancels the subscription via the API.

Webhook Handler

The webhook handler at billing/lemonSqueezy/webhook.ts is an HTTP action that verifies the HMAC signature and processes subscription/order events.

Variant ID Mapping

Lemon Squeezy uses variant IDs (numbers) instead of price IDs. The providerMapping.ts file maps these via environment variable names:

const lemonSqueezyVariantIdToPlanKey = {
  LEMON_SQUEEZY_PRO_MONTHLY_VARIANT_ID: "pro_monthly",
  LEMON_SQUEEZY_PRO_YEARLY_VARIANT_ID: "pro_yearly",
  LEMON_SQUEEZY_PRO_LIFETIME_VARIANT_ID: "pro_lifetime",
};

Test Mode

Set LEMON_SQUEEZY_TEST_MODE=true during development to use Lemon Squeezy's test environment. Switch to false for live payments.

Next Reads

On this page