Skip to content

Stripe Subscriptions

Fresh

Source: shipfa.st/docs/tutorials/subscriptions

INFO

The flow is the same for one-time payments. For Lemon Squeezy, see the Payments feature.

Prerequisites

Procedure

Step 1: Create a Stripe Product

  1. In Stripe Dashboard, click More+ > Product Catalog > + Add Product
  2. Set a name and monthly price
  3. Click Save Product
  4. Copy the price ID (starts with price_) to config.stripe.plans[0].priceId in config.js

Step 2: Add Checkout to Dashboard

javascript
import ButtonAccount from "@/components/ButtonAccount";
import ButtonCheckout from "@/components/ButtonCheckout";
import config from "@/config";

export const dynamic = "force-dynamic";

export default async function Dashboard() {
  return (
    <main className="min-h-screen p-8 pb-24">
      <section className="max-w-xl mx-auto space-y-8">
        <ButtonAccount />
        <h1 className="text-3xl md:text-4xl font-extrabold">
          Subscribe to get access:
        </h1>
        <ButtonCheckout
          mode="subscription"
          priceId={config.stripe.plans[0].priceId}
        />
      </section>
    </main>
  );
}

Step 3: Test the Payment

  1. Open http://localhost:3000/dashboard
  2. Log in and click the subscribe button
  3. Use test card: 4242 4242 4242 4242

Step 4: Webhook Handling

The webhook at /api/webhook/stripe/route.js handles:

  • Setting hasAccess boolean on the User model
  • Processing checkout.session.completed events

WARNING

You need a Stripe local endpoint running for dev mode.

Step 5: Customize

  • Add business logic in /api/webhook/stripe/route.js (abandoned cart emails, credits, etc.)
  • Users manage accounts with <ButtonAccount /> (cancel, update card)

Verification Checklist

  • [ ] Product created in Stripe with price ID
  • [ ] Price ID added to config.js
  • [ ] Test payment succeeds with 4242 card
  • [ ] Webhook sets hasAccess to true
  • [ ] ButtonAccount allows subscription management

See Also