• Create a new account on Stripe and activate payments
  • In your Settings → Business → Public Details, add your website URL
  • In your Settings → Business → Branding, add your logo & colours
  • In your Settings → Business→ Customer Emails, turn on emails for successful payments & refunds
  • In your Settings → Billing → Customer Portal, activate link to customer portal (in case you need later)
  • In the search box, type rules and click [Radar > Rules] , make sure the second 3DS rule is enabled Request 3DS if 3D Secure is recommended for card and turn on the third 3DS rule Request 3DS if 3D Secure is supported for card. Enable CVC check and block payments if CVC fails Block if CVC verification fails.
  • Turn ON Test Mode

One Time Payments

  • Create a new product and copy the price ID price_1ju5GD464564 in config.stripe.plans[0].priceId in to the config.js file.
  • In your Developers → API keys, copy your public & private keys and add them to the STRIPE_SECRET_KEY & STRIPE_PUBLIC_KEY in .env.local file.
  • To set up the webhook locally, follow the steps in Developers → Webhooks → Test in local environment. After login to Stripe CLI, use this command to forward webhook events to our API:


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

Copy the signing secret and add it to STRIPE_WEBHOOK_SECRET in .env.local file.


The flow is the same for one-time payments.

Let's create a Stripe Checkout to set up a subscription and let our webhook handle the logic to provision access to the user.

You need to have both Stripe & Database to complete this.

  • In your Stripe dashboard, Click [More +] → [Product Catalogue] → [+ Add Product]. Set a name and a monthly price (or anything according to your business model). Then click [Save Product].
  • In the [Pricing] section, copy the product price ID (starts with price_) and add it to the first plan in the stripe.plans array in the config.js file.
  • In /app/dashboard/page.js, paste this:
  • /app/dashboard/page.js

    1import ButtonAccount from "@/components/ButtonAccount";
    2import ButtonCheckout from "@/components/ButtonCheckout";
    3import config from "@/config";
    5export const dynamic = "force-dynamic";
    7export default async function Dashboard() {
    8  return (
    9    <main className="min-h-screen p-8 pb-24">
    10      <section className="max-w-xl mx-auto space-y-8">
    11        <ButtonAccount />
    13        <h1 className="text-3xl md:text-4xl font-extrabold">
    14          Subscribe to get access:
    15        </h1>
    17        <ButtonCheckout
    18          mode="subscription"
    19          priceId={config.stripe.plans[0].priceId}
    20        />
    21      </section>
    22    </main>
    23  );
  • Open http://localhost:3000/dashboard in your browser, log-in and click the button to make a payment with the credit card number 4242 4242 4242 4242 expiry date set to a future date and a random CVV number.
  • Our webhook /app/api/webhook/stripe/route.js listens to Stripe events and will handle the logic to provision access (or not) to the user—See the Boolean hasAccess in the User.js schema (NextAuth) or has_access in your Supabase profiles table.
  • You need to have a Stripe local endpoint running on your computer for this to work in dev mode.

  • You can add your own logic in /app/api/webhook/stripe/route.js like sending abandoned cart emails, remove credits, etc.
  • Users can manage their account with:
  • /app/dashboard/page.js

    1<ButtonAccount /> // (cancel subscription, update credit card, etc.)

That's it. You can build your SaaS on top of this flow!

Create Checkout

From the front-end, use theButtonCheckout component to automatically create a checkout session (one-time payment or subscription).

Stripe Webhooks

Our API listens to Stripe selected webhooks events & update the user accordingly. It turns boolean hasAccess (or has_access in Supabase) to true/false based on whether the user should have access to a paid resource or not.

You can add your own business logic to the /app/api/webhook/stripe/route.js API endpoint (add credits to a user, send email with a paid e-book etc.)

Production Checklist

  • Turn OFF Test Mode in your Stripe Dashboard
  • In your Developers → API keys copy your public & private keys and add them to STRIPE_SECRET_KEY & STRIPE_PUBLIC_KEY in your production environment variables.
  • In your Developers → Webhook → Add Endpoint. Set your domain + /api/webhook/stripe (i.e Select checkout.session.completed event (or more if needed). Copy the signing secret and add it to STRIPE_WEBHOOK_SECRET in your production environment variables.
  • Optional: In Settings → Business → Bank accounts and currencies, set a specific date of the month to receive your payouts (I use the 10th of each month)
  • Optional: In Settings → Business → Customer Emails, activate emails for successful payments & refunds