Claude Code Boilerplate
FeaturesPricingBlogDocs
Get started →

Product

  • Features
  • Pricing
  • Skills

Compare

  • vs ShipFast
  • vs MakerKit
  • vs supastarter

Resources

  • Docs
  • Blog
  • Discord

Legal

  • License
  • Privacy Policy
  • Terms of Service
Claude Code Boilerplate

© 2026 Claude Code Boilerplate. All rights reserved.

← All posts

Build an Online Course Platform With Next.js -- Own Your Students and Keep Every Dollar

July 12, 2026
nextjsstripesaasboilerplatepayments

Teaching platforms sound like a good deal until you do the math. Teachable charges up to 5% per transaction on its free plan. Podia takes a cut too. Gumroad charges 10%. On $10,000 in course sales, you hand $500 to $1,000 to a platform you do not control, cannot fully customize, and that can limit your account at any time.

Building your own course platform used to mean months of work: auth from scratch, payment flows, content delivery, enrollment emails, student progress. With the Next.js SaaS boilerplate, most of that foundation is already done.

What a course platform actually needs

Strip a course site down to its core and you have four pieces:

  1. Auth -- students create accounts and log in. Instructors manage content.
  2. Payments -- a student pays once (or subscribes) and gets access.
  3. Content gating -- only enrolled students see lesson pages.
  4. Delivery -- lessons, embedded video, downloadable files, and a progress tracker.

The boilerplate ships the first two fully built. Auth is JWT-based with bcrypt password hashing -- you can separate instructor and student roles using the RBAC pattern already in the codebase. For payments, Stripe one-time payments handles checkout, webhooks, and database updates out of the box.

Content gating and lesson delivery are the product you build on top.

Pick your payment model first

Before you write a line of schema, choose how you charge:

  • One-time purchase -- student pays $97 or $297, gets lifetime access. Simple, common for info products.
  • Subscription -- monthly access, cancel anytime. Works well for ongoing content or live cohorts.
  • Bundle -- pay once for a library of courses.

Stripe Checkout handles all three. The boilerplate ships with both subscription and one-time checkout flows -- you configure a price in the Stripe dashboard and point the checkout session at it. When payment succeeds, a Stripe webhook fires. Your webhook handler marks the user as enrolled and Resend sends a welcome email with the course link. That email flow follows the pattern in transactional email with Resend.

Gating lessons to paying students

Content gating lives in the service layer, not in middleware. You add an enrollments table with user_id and course_id, then check enrollment before rendering any lesson:

// modules/enrollment/enrollment.service.ts
async function requireEnrollment(userId: string, courseId: string) {
  const enrollment = await enrollmentRepo.find(userId, courseId);
  if (!enrollment) throw new HttpError(403, 'Not enrolled');
}

Call this at the top of any server component that renders lesson content. Non-enrolled visitors get a 403 and you redirect them to the sales page. This mirrors the plan-gating pattern already in the codebase, so you are extending something you already understand.

What about video hosting?

The boilerplate does not ship a video player -- and you should not build one. Host videos on YouTube (unlisted links), Vimeo (with domain privacy), or Cloudflare Stream. Embed with a standard <iframe>. The boilerplate's Cloudinary integration handles downloadable worksheets, PDFs, and slide decks.

This is the right tradeoff for a first version. You own the enrollment records, the payment flow, and the student relationship. Those are what matter for your business. The video hosting is a solved, cheap commodity.

What you end up with

Building the course-specific pieces on top of the boilerplate gives you:

  • A course sales page with a Stripe Checkout button
  • Student accounts with JWT auth and enrollment records in Neon DB
  • Lesson pages gated behind a paid check
  • A Stripe webhook that enrolls students the moment payment clears
  • An enrollment confirmation email via Resend
  • Drizzle ORM migrations for courses, lessons, and enrollments
  • An optional progress-tracking table if you want to show completion percentages

The only thing a hosted platform buys you that this does not is its built-in audience. If you have your own -- an email list, a social following, a community -- you do not need the platform. You need the infrastructure.

The revenue math

Say you sell a course at $297 and move 50 enrollments in your first launch.

  • Teachable (free plan, 5% transaction fee): you lose $742 to fees
  • Podia (Starter, $9/month + 8% fee): you lose ~$1,200 to fees
  • Your own platform: you pay Stripe's 2.9% + 30 cents per transaction (~$445 total) plus Vercel at $20/month and Neon DB on its free tier for the first year

The boilerplate pays for itself inside the first launch, and your student list belongs to you permanently.

Start building

Clone the Next.js SaaS boilerplate and you start with auth, Stripe, and email already wired. Add the enrollment table, the lesson pages, and the gating check -- and you have a course platform that costs you a fraction of what Teachable charges, while keeping every student relationship you build.