Commerce setup
Premium content gating and learning path purchases require Stripe. This guide covers what editors need to know; technical env setup is in Environment variables and Production deployment.
What Stripe powers
| Flow | User entry | Result |
|---|---|---|
| Premium subscription | /pricing or account upgrade |
User.plan → Premium |
| Learning path purchase | Path detail "Buy" button | learningPathPurchase record |
Both flows use POST /api/stripe/checkout and confirm via POST /api/stripe/webhook.
Required environment variables
| Variable | Purpose |
|---|---|
STRIPE_SECRET_KEY |
Server-side API (required at build/runtime) |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Client-side checkout |
STRIPE_WEBHOOK_SECRET |
Verify webhook signatures |
STRIPE_PREMIUM_MONTHLY_PRICE_ID |
Monthly subscription price ID |
STRIPE_PREMIUM_ANNUAL_PRICE_ID |
Annual subscription price ID |
NEXT_PUBLIC_SITE_URL |
Checkout success/cancel redirect URLs |
Use test keys locally (sk_test_…, pk_test_…) and live keys in production only on your production host.
Finding API keys (current Stripe Dashboard)
Stripe’s layout changed in 2025–2026. You may see Workbench / Developers in the sidebar, or only Home, Payments, Billing, and More. Use any of these paths:
| Goal | How to get there |
|---|---|
| API keys (fastest) | Open dashboard.stripe.com/test/apikeys for test keys, or dashboard.stripe.com/apikeys for live keys |
| From the sidebar | More → Developers → API keys, or top Developers area → API keys |
| Test vs live | Use View test data (top of Dashboard). When on, the API keys page shows sandbox/test keys (pk_test_, sk_test_). When off, you see live keys (pk_live_, sk_live_). |
On the API keys page you’ll see two sections:
| Section | Use for THE HCLAB? |
|---|---|
| Standard keys | Yes — copy Publishable key → NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, and Secret key (click Reveal test key / Reveal live key) → STRIPE_SECRET_KEY |
| Restricted keys | Optional later (rk_…) — scoped permissions; do not substitute for the standard secret key unless you configure the right scopes |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY is the full Publishable key token from the Standard keys table (starts with pk_test_ or pk_live_, usually 50+ characters). It is not a restricted key (rk_…) and not the secret key.
For local development, turn View test data on and use only pk_test_ / sk_test_ in .env. Never use live keys on localhost.
Stripe Dashboard setup
1. Create products and prices
Open Product catalog in the sidebar (or Products in older layouts), then:
- Create Premium product
- Add recurring prices: monthly and annual
- Copy price IDs to
STRIPE_PREMIUM_MONTHLY_PRICE_IDandSTRIPE_PREMIUM_ANNUAL_PRICE_ID
Learning path purchases do not need pre-created Stripe prices — checkout uses dynamic price_data from the path's CMS price field.
2. Configure webhook
In Developers → Webhooks (or dashboard.stripe.com/test/webhooks for test mode), Add endpoint:
https://your-domain.com/api/stripe/webhook
Subscribe to events:
checkout.session.completedcustomer.subscription.updatedcustomer.subscription.deleted
Open the endpoint → Signing secret → copy to STRIPE_WEBHOOK_SECRET (whsec_…).
For local testing, use the Stripe CLI (recommended — no Dashboard endpoint needed on localhost):
stripe listen --forward-to localhost:3000/api/stripe/webhook
CMS: learning path pricing
On /admin/learning-paths/new or edit:
| Field | Behavior |
|---|---|
| One-time price (USD) | Whole dollars (e.g. 49 = $49.00). Stored in cents internally. |
| Blank price | Path cannot be purchased individually — access via plan only |
| Visibility | Still applies — Premium visibility + price means "subscribers OR buyers" |
After saving a priced path:
- Publish the path
- Visit
/learning-paths/[slug]as a free member - Click purchase → Stripe Checkout
- Complete test payment → redirect with
?purchased=1 - Verify access and record on
/account
CMS: premium content
Set Visibility → Premium on any gated content type. No per-item Stripe config — one subscription unlocks all Premium-tier content.
Before publishing Premium content:
- Stripe keys and price IDs configured
- Webhook endpoint live and receiving events
- Test subscription on
/pricingupgrades a test user to Premium - Gated content accessible after upgrade
What happens on payment
Subscription checkout
- User clicks upgrade on
/pricing - Checkout session created with customer metadata (
userId) - Webhook
checkout.session.completed→ retrieves subscription → setsUser.plan = PREMIUM, storesstripeSubscriptionId - Subscription changes/deletions update plan via webhook
Path purchase
- Authenticated user buys a priced path
- One-time Checkout session with path title and price
- Webhook creates
learningPathPurchasewith amount paid - User gains path access even without Premium plan
Admin visibility
/admin dashboard shows subscription counts and path purchase revenue when data exists.
/admin/users — manually set plan (Free, Subscriber, Premium, Enterprise) for comped access without Stripe.
Member account
/account displays:
- Current plan badge
- Upgrade button (free users)
- Purchased learning paths
- Path progress and certifications
Editor checklist
| Task | Where |
|---|---|
| Set path price | /admin/learning-paths → One-time price field |
| Gate content | Any CMS form → Visibility → Premium |
| Verify purchase flow | Public path page → test checkout |
| Verify subscription | /pricing → test checkout |
| Comp a user | /admin/users → set plan to Premium |
Related docs
- Access & gating — visibility tiers and teasers
- Learning paths — path pricing and certification
- Commerce & plans — platform overview