Stripe Setup
Subscriptions per workspace: create Dashboard products/prices, paste IDs into env, then register the webhook endpoint this repo expects.
1. Create products and prices
In the Stripe Dashboard:
- Go to Products → Add product
- Create your plans (e.g., Starter, Pro, Enterprise)
- For each plan, add a recurring price (monthly and/or yearly)
- Copy the Price ID for each price (starts with
price_)
2. Configure environment variables
STRIPE_SECRET_KEY=sk_live_... # or sk_test_... for development
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
# Price IDs (comma-separated for multiple billing periods)
STRIPE_STARTER_PRICE_ID=price_starter_monthly,price_starter_yearly
STRIPE_PRO_PRICE_ID=price_pro_monthly,price_pro_yearly
STRIPE_ENTERPRISE_PRICE_ID=price_enterprise_monthly,price_enterprise_yearly
# Used in billing UI (public)
NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PRICE_ID=price_pro_monthly
NEXT_PUBLIC_STRIPE_PRO_YEARLY_PRICE_ID=price_pro_yearly
NEXT_PUBLIC_STRIPE_ENTERPRISE_MONTHLY_PRICE_ID=price_enterprise_monthly
NEXT_PUBLIC_STRIPE_ENTERPRISE_YEARLY_PRICE_ID=price_enterprise_yearly
3. Set up the webhook
Local development
Use the Stripe CLI to forward webhooks:
stripe listen --forward-to localhost:3000/api/stripe/webhook
Copy the webhook signing secret from the CLI output to STRIPE_WEBHOOK_SECRET.
Production
In Stripe Dashboard → Developers → Webhooks:
- Add endpoint:
https://your-app.com/api/stripe/webhook - Select events:
checkout.session.completedcustomer.subscription.updatedcustomer.subscription.deleted
- Copy the signing secret to
STRIPE_WEBHOOK_SECRET
4. How billing works
- Workspace OWNER clicks Upgrade →
createCheckoutSession()server action - Stripe Checkout session created → user redirected to Stripe
- After payment → Stripe sends
checkout.session.completedevent - Webhook handler at
/api/stripe/webhookupsertssubscriptionsrow - User redirected back to
/w/[workspaceId]/billing?success=1
The subscriptions table stores:
stripe_customer_id: for Customer Portal sessionsstripe_subscription_id: for webhook matchingplan: derived from the price ID (starter,pro,enterprise)status: mirrors Stripe subscription statuscurrent_period_end: for displaying renewal date
5. Test the flow
Use Stripe's test card: 4242 4242 4242 4242 with any future expiry and any CVC.