Stripe Setup
Configure Stripe for subscription payments — products, prices, webhooks, test mode, and going live.
Stripe Setup
ScaleRocket uses Stripe for subscription billing. Users pick a plan on the pricing page, checkout via Stripe, and their subscription state syncs back to your database via webhooks.
Important: You'll set up everything in Test mode first. When you're ready to accept real payments, you'll redo the setup in Live mode — products, prices, and webhooks are completely separate between the two modes. Nothing carries over.
Step 1: Create a Stripe Account
- Go to stripe.com and sign up
- You start in Test mode by default (toggle in the top-left corner)
- Keep Test mode active for now — you'll switch to Live mode when deploying to production
Step 2: Create Products and Prices (Test Mode)
You have two options: manually via the Stripe Dashboard, or automatically via the Stripe MCP.
Option A: Manual (Stripe Dashboard)
- In the Stripe Dashboard, make sure you're in Test mode
- Go to Product catalog → Add product
- Fill in:
- Name — e.g., "Starter"
- Description — e.g., "For individuals getting started"
- Add two prices:
- Monthly — e.g., $29/month (Recurring)
- Yearly — e.g., $290/year (Recurring)
- Click Save product
- Copy each Price ID from the product detail page (starts with
price_) - Repeat for each plan (Starter, Pro, Agency)
Option B: Via AI + MCP (Recommended for Vibecoders)
If you have the Stripe MCP configured in your .mcp.json, you can ask your AI assistant to create the products for you:
Prompt: "Create 3 Stripe products in TEST mode for my SaaS:
- Starter — $29/month, $290/year
- Pro — $79/month, $790/year
- Agency — $199/month, $1990/year Each product needs both a monthly and yearly recurring price. Give me the Price IDs for each."
The AI will create the products and return the Price IDs. Copy them for the next step.
Step 3: Configure Pricing in Your App
Open the pricing configuration and replace the placeholder Price IDs with the real test ones:
// packages/config/src/pricing.ts
export const pricingPlans: PricingPlan[] = [
{
id: "starter",
name: "Starter",
description: "For individuals getting started",
price: { monthly: 29, yearly: 290 },
stripePriceId: {
monthly: "price_1Abc...", // ← Your TEST mode Price ID
yearly: "price_1Def...", // ← Your TEST mode Price ID
},
features: ["50 credits/month", "Email support", "PNG/JPG exports"],
limits: { credits: 50, storage: "1GB", apiAccess: false },
},
// ... Pro and Agency plans
];You also need to update the PRICE_TO_PLAN mapping in the webhook function so it knows which Stripe Price ID corresponds to which plan:
// supabase/functions/stripe-webhook/index.ts
const PRICE_TO_PLAN: Record<string, string> = {
"price_1Abc...": "starter", // monthly
"price_1Def...": "starter", // yearly
"price_1Ghi...": "pro", // monthly
"price_1Jkl...": "pro", // yearly
"price_1Mno...": "agency", // monthly
"price_1Pqr...": "agency", // yearly
};// convex/stripe.ts
const PRICE_TO_PLAN: Record<string, string> = {
"price_1Abc...": "starter", // monthly
"price_1Def...": "starter", // yearly
"price_1Ghi...": "pro", // monthly
"price_1Jkl...": "pro", // yearly
"price_1Mno...": "agency", // monthly
"price_1Pqr...": "agency", // yearly
};Step 4: Set Up Webhooks (Test Mode)
Stripe sends events (subscription created, payment succeeded, etc.) to your webhook endpoint. ScaleRocket processes these via your backend.
Local Development
Use the Stripe CLI to forward events to your local environment:
# Install the Stripe CLI
brew install stripe/stripe-cli/stripe # macOS
# or: scoop install stripe # Windows
# or: see https://stripe.com/docs/stripe-cli
# Login to your Stripe account
stripe login# Forward webhooks to your local Supabase Edge Function
stripe listen --forward-to http://localhost:54321/functions/v1/stripe-webhookThe CLI outputs a webhook signing secret (starts with whsec_). Add it to your local Supabase env:
# supabase/.env
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...# Forward webhooks to your local Convex HTTP endpoint
stripe listen --forward-to http://localhost:3210/stripe-webhookThe CLI outputs a webhook signing secret (starts with whsec_). Add it to your Convex environment:
npx convex env set STRIPE_SECRET_KEY sk_test_...
npx convex env set STRIPE_WEBHOOK_SECRET whsec_...Keep the CLI running in a separate terminal while you develop. It must be active for webhooks to reach your local server.
Step 5: Set Environment Variables (Test Mode)
# apps/app/.env.local — client-side (safe to expose)
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
# supabase/.env — server-side (Edge Functions)
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...Security: The publishable key (
pk_test_) is safe for client-side code. The secret key (sk_test_) and webhook secret (whsec_) must ONLY be in Supabase Edge Function secrets — never in frontend code.
# apps/app/.env.local — client-side (safe to expose)
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
# Convex environment variables — server-side
npx convex env set STRIPE_SECRET_KEY sk_test_...
npx convex env set STRIPE_WEBHOOK_SECRET whsec_...Security: The publishable key (
pk_test_) is safe for client-side code. The secret key (sk_test_) and webhook secret (whsec_) must ONLY be in Convex environment variables — never in frontend code.
Step 6: Test a Payment
- Start your dev server:
pnpm dev - Start Supabase locally:
npx supabase start - Start the Stripe CLI webhook forwarder (Step 4)
- Go to
localhost:5173/billing(dashboard app) - Click a plan and complete checkout with the test card:
| Card Number | Scenario |
|---|---|
4242 4242 4242 4242 | Successful payment |
4000 0000 0000 3220 | 3D Secure required |
4000 0000 0000 9995 | Payment declined |
4000 0000 0000 0341 | Attaching card fails |
Use any future expiry date and any 3-digit CVC.
After checkout, verify:
- The
subscriptionstable in Supabase has a new row withstatus: "active" - The
creditstable has been updated with the plan's monthly allowance - The user's dashboard shows the active plan and credit balance
- Stripe Dashboard shows the subscription under Customers
Going Live: Switch to Production
When you're ready to accept real payments, you need to redo the entire Stripe setup in Live mode. Test mode and Live mode are completely separate — products, prices, customers, and webhooks do NOT transfer.
Checklist for going live:
1. Activate your Stripe account
Complete the business verification in Stripe Dashboard → Settings → Business details. You'll need your business name, address, and bank account.
2. Recreate products and prices in Live mode
Switch to Live mode in the Stripe Dashboard (toggle top-left), then recreate all your products and prices.
Manual: Same process as Step 2 Option A, but in Live mode.
Via AI + MCP: If you used the MCP to create test products, you must recreate them in Live mode too:
Prompt: "Switch my Stripe to LIVE mode and recreate these 3 products:
- Starter — $29/month, $290/year
- Pro — $79/month, $790/year
- Agency — $199/month, $1990/year Give me the new LIVE Price IDs."
3. Update Price IDs in your code
Replace ALL test Price IDs with the new live ones in:
packages/config/src/pricing.ts → stripePriceId fields
supabase/functions/stripe-webhook/index.ts → PRICE_TO_PLAN mapping (Supabase)
convex/stripe.ts → PRICE_TO_PLAN mapping (Convex)4. Create a Live webhook
- Go to Developers → Webhooks in Stripe Dashboard (make sure you're in Live mode)
- Click Add endpoint
- Set the URL to your backend endpoint:
https://YOUR_PROJECT_REF.supabase.co/functions/v1/stripe-webhookhttps://YOUR_DEPLOYMENT.convex.site/stripe-webhook- Select these events:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
- Click Add endpoint
- Copy the Signing secret (
whsec_...)
Critical: This is a NEW webhook with a NEW signing secret. Your test webhook is separate and still active for development.
5. Update production secrets
npx supabase secrets set STRIPE_SECRET_KEY=sk_live_...
npx supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_... # ← the LIVE signing secretnpx convex env set STRIPE_SECRET_KEY sk_live_...
npx convex env set STRIPE_WEBHOOK_SECRET whsec_... # ← the LIVE signing secret6. Update the publishable key
In your Vercel dashboard for apps/app, update:
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...7. Test with a real card
Make a small real purchase ($1 or your cheapest plan), verify the subscription is created, then refund it in the Stripe Dashboard.
Summary: Test vs Live
| Test Mode | Live Mode | |
|---|---|---|
| Keys | sk_test_... / pk_test_... | sk_live_... / pk_live_... |
| Products/Prices | Created in test mode | Must be recreated in live mode |
| Price IDs | Different | Different (must update code) |
| Webhook | CLI forwarding or test endpoint | Production endpoint on Supabase |
| Webhook Secret | From CLI or test webhook | From live webhook |
| Cards | Test cards only (4242...) | Real cards |
| Money | No real charges | Real charges |
| MCP | Creates in test mode | Must recreate in live mode |
Next Steps
- Set up transactional emails for payment receipts
- Configure the credits system for usage-based billing
- Deploy to production with the full production checklist
Done reading? Mark this page as complete.