Billing

Nuxtbe comes with prebuild support for Stripe and LemonSqueezy. Learn how to configure them.

Stripe

Stripe is one of the options for handling payments. In order to enable Stripe as a payment provider, you need to do following steps:

Create Stripe secret key

  1. Open the API keys page in your Stripe Dashboard.
  2. Click "Create secret key" button in the top right.
  3. Wait for the verification code sent to your email or phone. Enter the code when prompted. Click "Continue" if needed.
  4. Enter a descriptive name in the "Key name" field (e.g., "Nuxtbe Production" or "Nuxtbe Development").
  5. Click "Create" to generate the key.
  6. Copy the displayed secret key by clicking on it.
  7. Store the key in .env file as STRIPE_SERVER_SECRET_KEY.
.env
STRIPE_SERVER_SECRET_KEY="sk_test_..."
  1. Add a note about where you stored the key and click "Done".

Create Stripe webhook

  1. Go to the Webhooks page in your Stripe Dashboard.
  2. Click "Create an event destination" button.
  3. Enter your endpoint URL:
https://your-domain.com/api/webhook/stripe
  1. Select events to listen to:
    • checkout.session.completed
    • customer.subscription.deleted
    • customer.subscription.updated

Feel free to add more events if you need them. But do not forget to handle them in the server/api/webhook/stripe.post.ts file.

  1. Click "Add endpoint" to create the webhook.
  2. Copy the "Signing secret" that appears.
  3. Store the signing secret in .env file as STRIPE_WEBHOOK_SECRET:

Configure Stripe Customer Portal

Stripe requires you to configure the Customer Portal. You can do this by going to the Customer Portal in your Stripe Dashboard.

Stripe Customer Portal

Also i recommend to Limit customers to only one subscription at a time. It can be done in the Customer Portal settings.

Stripe Customer Portal

Configure app.config.ts

Nuxtbe handles payments via Stripe automatically, you just need to specify some configuration in the app.config.ts file. Moreover it already comes with predefined example plans.

app.config.ts
export default defineAppConfig({
 ...
 billing: {
    billingProvider: 'stripe',
    allowUnauthenticated: true,
    customerPortalUrl: 'https://billing.stripe.com/p/login/your-customer-portal-url',
    isSubscription: true,
    featuredBadgeText: 'Most popular',
    yearSavings: 25,
    plans: [
      {
        productId: 'your-product-id',
        paymentLink: {
          monthly: 'link-to-monthly-payment',
          yearly: 'link-to-yearly-payment',
          oneTime: 'link-to-one-time-payment',
        },
        name: 'Starter',
        priceMonth: 10,
        priceYear: 100,
        description: 'Get started with basic plan',
        features: [
          'Access to basic components',
          'Unlimited projects',
          'Custom domain',
          '24/7 support',
        ],
        notAvailableFeatures: [
          'Advanced analytics',
          'Premium components',
        ],
        buttonText: 'Get started',
        buttonVariant: 'outline',
        isFeatured: false,
      },
      ...
    ],
  },
});
billingProviderrequired'lemonsqueezy' | 'stripe'
allowUnauthenticatedboolean
customerPortalUrlrequiredstring
isSubscriptionboolean
featuredBadgeTextstring
yearSavingsnumber
plansrequiredPlan[]

Testing Stripe payments

To test if everything works fine, go to the pricing page and try to subscribe to a plan. You have to be redirected to the checkout page.

Stripe Checkout

Testing Stripe locally

Stripe provide Stripe CLI for local testing. All you need to do is to login and run listen command.

terminal
stripe login

Then run

terminal
stripe listen --forward-to localhost:3000/api/webhook/stripe

It will listen for events and forward them to your local server.

LemonSqueezy

Nuxtbe comes with built-in support for LemonSqueezy as a payment provider. This guide will help you set up and configure LemonSqueezy for your application.

Create LemonSqueezy Account

  1. Sign up for a LemonSqueezy account.
  2. Complete your store setup in the LemonSqueezy dashboard.

Generate API Key

  1. Navigate to the API Keys section in your LemonSqueezy dashboard.
  2. Click + button to generate new key.
  3. Give your key a descriptive name (e.g., "Nuxtbe Production").
  4. Copy the generated API key.
  5. Store it in your .env file:
.env
LEMONSQUEEZY_API_KEY="your-api-key-here"

Configure Webhook

  1. Go to the Webhooks section in your LemonSqueezy dashboard.
  2. Click "Add webhook".
  3. Enter your endpoint URL:
https://your-domain.com/api/webhook/lemonsqueezy
  1. Select the following events to listen to:
    • order_created - Triggered when a payment is successfully processed
    • subscription_plan_changed - Triggered when a user changes their subscription plan
    • subscription_expired - Triggered when a subscription expires
  2. Copy the signing secret.
  3. Store it in your .env file:
.env
LEMONSQUEEZY_WEBHOOK_SECRET="your-webhook-secret"

Create Products and Variants

  1. Create your products in the Products section.
  2. For each product:
    • Set up pricing variants (monthly/yearly)
    • Configure subscription options if needed
    • Note down the product and variant IDs for configuration

Configure app.config.ts

Configure LemonSqueezy in your app.config.ts:

app.config.ts
export default defineAppConfig({
  // ... other config
  billing: {
    billingProvider: 'lemonsqueezy',
    allowUnauthenticated: true,
    customerPortalUrl: 'https://app.lemonsqueezy.com/billing',
    isSubscription: true,
    featuredBadgeText: 'Most popular',
    yearSavings: 25,
    plans: [
      {
        productId: 'your-product-id',
        paymentLink: {
          monthly: 'https://your-store.lemonsqueezy.com/checkout/buy/variant-id',
          yearly: 'https://your-store.lemonsqueezy.com/checkout/buy/variant-id',
        },
        name: 'Starter',
        priceMonth: 10,
        priceYear: 100,
        description: 'Perfect for small teams',
        features: [
          'Basic features',
          'Email support',
          '5 team members',
        ],
        notAvailableFeatures: [
          'Advanced analytics',
          'Priority support',
        ],
        buttonText: 'Get Started',
        buttonVariant: 'outline',
        isFeatured: false,
      },
      // Add more plans...
    ],
  },
});
billingProviderrequired'lemonsqueezy' | 'stripe'
allowUnauthenticatedboolean
customerPortalUrlrequiredstring
isSubscriptionboolean
yearSavingsnumber
plansrequiredPlan[]

Testing Locally

To test webhooks locally:

With ngrok

  1. Install ngrok
  2. Run your Nuxt application
  3. Start ngrok:
ngrok http 3000
  1. Use the generated ngrok URL in your LemonSqueezy webhook settings
  2. Test a purchase using LemonSqueezy's test mode

With Cloudflare Tunnel

Or you can use dev with --tunnel flag to automatically generate a tunnel for you.

  1. Run dev with tunnel flag
npm
pnpm
bun
npm run dev --tunnel
  1. Use the generated URL in your LemonSqueezy webhook settings. The URL will be shown in the console and will be something like https://<random-string>.trycloudflare.com.
  2. Test a purchase using LemonSqueezy's test mode

Usage Example

The pricing component will automatically use your LemonSqueezy configuration:

<template>
  <PricingTable />
</template>

Pricing Component

Additional Resources