Project Set Up

Course: Integrate Stripe Subscriptions with Next.js

Introduction

Subscriptions are one of the most common ways to monetize an app, but setting them up can feel overwhelming at first. In this course, we’ll walk through how to integrate Stripe subscriptions into a Next.js application step by step.

By the end, you’ll have a working subscription system that’s production-ready, scalable, and doesn’t require building all the billing logic from scratch.

Install/Set Up Project

Since the focus of this course is Stripe implementation, we'll be building off of our code from the auth course where we set up authentication and RBAC in Next.js. You can skip this step if you are integrating Stripe into your own app.

The project has already been configured with a user schema and database, so we'll add on to that instead of creating this project from scratch.

You can use this course to implement Stripe into your own app, the logic will work the same. If you want, you can also download the starter code from the following github link to follow along: https://github.com/fullstacked-dev/session-auth

If you're following along, go ahead and clone the repo. When you do that, you'll also need to run the following in the terminal to remove the .git file so that you're not committing to the same repo:

rm -rf .git

Then install the dependencies by running the following command in the terminal:

npm install

Great! Now that we have our starter code, we'll need to update our database a bit to accommodate for Stripe.

Update Database

Now you'll need to connect your database to the project. Create a .env file and add your DATABASE_URL to it. After that is done, we will need to update the user model. It currently does not have a column for the type of membership, so we'll need to create it.

In the schema.prisma file, we'll add an enum and update the User model:

enum Plan {
  free
  premium
  pro
}

model User {
  id String @id @default(uuid())
  email String @unique
  password String
  salt String
  role Role @default(user)
  plan Plan @default(free)
  stripeCustomerId String?
  stripeSubscriptionId String?
  stripePriceId String?
  stripeCurrentPeriodEnd DateTime?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

We added a Plan enum to indicate the plan the user is on. We also add some additional fields to track the users Stripe ID, their Subscription ID, and Price ID (essentially the product ID in Stripe). We also add the end of their current period.

Then run the following commands in the terminal

npx prisma generate
npx prisma migrate dev

Set Up Stripe

Now let's get Stripe set up before diving into any of the code.

Register for a Stripe account if you haven't already. Make sure you are in the sandbox (test environment). The add the following to your .env file:

STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...

Create the product in Stripe (Dashboard > Product Catalog > Add Product)

npm install stripe @stripe/stripe-js

Lastly, we'll initialize the Stripe Client in the lib folder, create a stripe.ts file and add the following:

import Stripe from "stripe"

if (!process.env.STRIPE_SECRET_KEY) {
  throw new Error("STRIPE_SECRET_KEY is not set")
}

export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)

export const STRIPE_PUBLISHABLE_KEY = process.env.STRIPE_PUBLISHABLE_KEY!

export const STRIPE_PRICE_IDS = {
  premium: "your_stripe_price_id",
  pro: "your_stripe_price_id",
} as const

export type StripePriceId = keyof typeof STRIPE_PRICE_IDS

To get the Stripe Price ID, you'll need to click into the product and look for the id that starts with "price" and NOT "prod". Go and update the STRIPE_PRICE_IDS above.