← marketplace
creatorsconceptsha:518039b23eece6a9manual
course-landing-with-stripe
Use when shipping a course or digital-product landing page with email capture, Stripe Checkout, webhook fulfillment, and post-purchase drip emails — end-to-end in one pass with no SaaS subscription.
Tutorials · creator-attached
One-line install
curl --create-dirs -fsSL https://skillmake.xyz/i/course-landing-with-stripe -o ~/.claude/skills/course-landing-with-stripe/SKILL.md
The hash above pins this exact content. The file we serve at /api/marketplace/course-landing-with-stripe-518039b2/raw always matches sha:518039b23eece6a9.
3,902 chars · ~976 tokens
--- name: course-landing-with-stripe description: Use when shipping a course or digital-product landing page with email capture, Stripe Checkout, webhook fulfillment, and post-purchase drip emails — end-to-end in one pass with no SaaS subscription. source: https://docs.stripe.com/checkout/quickstart generated: 2026-05-07T21:42:19.592Z category: concept audience: creators --- ## Tutorials - https://skillmake.xyz/v/course-landing-with-stripe.mp4 ## When to use - Selling a course / template / mini-product without using Gumroad/Teachable/Podia - Owning the customer email + analytics rather than handing them to a platform - Wiring Stripe Checkout → webhook → grant access → drip onboarding emails - Adding upsell/order-bump in a way that keeps the checkout single-page ## Key concepts ### Checkout vs Payment Intents Stripe Checkout is the hosted page — fastest to ship, takes 30 minutes, handles taxes/cards/Apple Pay automatically. Payment Intents is for custom UI; only worth it if Checkout's brand fit blocks the sale. Default: Checkout. ### fulfillment via webhook Stripe redirects on success but you can't trust client-side success. The webhook (checkout.session.completed) is the source of truth for fulfillment: grant access, send delivery email, log to analytics. Verify the signature with stripe.webhooks.constructEvent. ### drip onboarding 5-email sequence triggered on purchase: day 0 (delivery + welcome), day 1 (first lesson + community link), day 3 (second lesson + ask for feedback), day 7 (bonus + cross-sell), day 30 (testimonial ask). Resend + Inngest is the cleanest stack for this. ## API reference ``` Create Checkout Session ``` Server-side route the landing page POSTs to. Returns the hosted Checkout URL; client redirects. ``` // app/api/checkout/route.ts import Stripe from 'stripe'; import { NextResponse } from 'next/server'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); export async function POST(req: Request) { const { email } = await req.json(); const session = await stripe.checkout.sessions.create({ mode: 'payment', customer_email: email, line_items: [{ price: process.env.STRIPE_PRICE_ID!, quantity: 1 }], success_url: `${process.env.SITE_URL}/thanks?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${process.env.SITE_URL}/`, allow_promotion_codes: true, }); return NextResponse.json({ url: session.url }); } ``` ``` Webhook handler with signature verification ``` Verifies the Stripe signature, then fulfills the order. Anything not behind this verification is unsafe. ``` // app/api/stripe-webhook/route.ts export const runtime = 'nodejs'; export async function POST(req: Request) { const sig = req.headers.get('stripe-signature')!; const body = await req.text(); let event; try { event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!); } catch { return new Response('bad sig', { status: 400 }); } if (event.type === 'checkout.session.completed') { const s = event.data.object; await grantAccess(s.customer_email!, s.metadata?.product_id); await sendDeliveryEmail(s.customer_email!); await scheduleDrip(s.customer_email!); } return new Response('ok'); } ``` ## Gotchas - Never grant access from the success page — always wait for the webhook. Otherwise a bad actor can spoof the success URL. - Set the webhook to deliver to your prod URL, not localhost. Use Stripe CLI's `stripe listen --forward-to` for local dev. - Tax handling: enable automatic_tax in Checkout if you sell internationally — manual tax math gets you in trouble fast. - Always store the email + Stripe customer id in your DB on fulfillment so refunds and re-deliveries work without searching Stripe. --- Generated by SkillMake from https://docs.stripe.com/checkout/quickstart on 2026-05-07T21:42:19.592Z. Verify against source before relying on details.
File: ~/.claude/skills/course-landing-with-stripe/SKILL.md