shipanysaas
Documentation
Back
  • Getting started
    • Install and run
    • Project structure
    • Configuration
    • Commands
  • Coding agents
    • Agent skills
  • Authentication
    • Email sign-in
    • OAuth providers
    • Two-step sign-in and passkeys
  • Database
    • Migrations
    • Row-level security
    • Database tests
    • Reading and writing data
  • Features
    • Teams and invitations
    • Email
    • File uploads
    • Blog, docs and changelog
  • Billing
    • Stripe and Lemon Squeezy
    • Pricing plans
    • Webhooks
  • Live demo
  • Stripe and Lemon Squeezy

    The environment variables and settings for each payment provider, and how to switch between them.

    Choose the provider

    Set the provider in two places so the app and the database agree:

    1. NEXT_PUBLIC_BILLING_PROVIDER=stripe or lemon-squeezy.
    2. billing_provider in the public.config row (stripe by default, from apps/web/supabase/schemas/02-config.sql).

    billing.config.ts is validated against the provider at build time.

    Stripe

    VariableNotes
    STRIPE_SECRET_KEYServer only. Must start with sk_ or rk_
    STRIPE_WEBHOOK_SECRETServer only. Must start with whsec_
    NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYMust start with pk_. Required unless you use the hosted checkout page
    STRIPE_UI_MODEembedded_page (default) shows checkout inside your app; hosted_page sends users to Stripe's page
    STRIPE_ENABLE_TRIAL_WITHOUT_CCtrue lets users start a plan's trial without entering a card

    The Stripe package checks these prefixes and stops with a message naming the variable if one is wrong.

    In the Stripe dashboard:

    • Create the products and prices, and copy each price id into billing.config.ts.
    • Add a webhook endpoint for https://<your-domain>/api/billing/webhook. The handler acts on checkout.session.completed, checkout.session.async_payment_succeeded, checkout.session.async_payment_failed, customer.subscription.updated, customer.subscription.deleted and invoice.paid.
    • Turn on the customer portal so users can manage their plan.

    Lemon Squeezy

    VariableNotes
    LEMON_SQUEEZY_SECRET_KEYAPI key, server only
    LEMON_SQUEEZY_SIGNING_SECRETThe webhook signing secret
    LEMON_SQUEEZY_STORE_IDYour store id

    In Lemon Squeezy:

    • Create the products and variants, and use the variant ids as line item ids in billing.config.ts.
    • Add a webhook for https://<your-domain>/api/billing/webhook with the signing secret above. The handler acts on order_created, subscription_created, subscription_updated, subscription_expired and subscription_payment_success.

    Lemon Squeezy plans can have only one line item. The config schema rejects more.

    Test mode

    Use test keys while you build. With Stripe test mode, the card 4242 4242 4242 4242 completes checkout. Run pnpm stripe:listen to receive webhooks locally (see Webhooks).