ScaleRocket/Web

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

  1. Go to stripe.com and sign up
  2. You start in Test mode by default (toggle in the top-left corner)
  3. 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)

  1. In the Stripe Dashboard, make sure you're in Test mode
  2. Go to Product catalogAdd product
  3. Fill in:
    • Name — e.g., "Starter"
    • Description — e.g., "For individuals getting started"
  4. Add two prices:
    • Monthly — e.g., $29/month (Recurring)
    • Yearly — e.g., $290/year (Recurring)
  5. Click Save product
  6. Copy each Price ID from the product detail page (starts with price_)
  7. Repeat for each plan (Starter, Pro, Agency)

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:

  1. Starter — $29/month, $290/year
  2. Pro — $79/month, $790/year
  3. 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-webhook

The 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-webhook

The 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

  1. Start your dev server: pnpm dev
  2. Start Supabase locally: npx supabase start
  3. Start the Stripe CLI webhook forwarder (Step 4)
  4. Go to localhost:5173/billing (dashboard app)
  5. Click a plan and complete checkout with the test card:
Card NumberScenario
4242 4242 4242 4242Successful payment
4000 0000 0000 32203D Secure required
4000 0000 0000 9995Payment declined
4000 0000 0000 0341Attaching card fails

Use any future expiry date and any 3-digit CVC.

After checkout, verify:

  • The subscriptions table in Supabase has a new row with status: "active"
  • The credits table 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:

  1. Starter — $29/month, $290/year
  2. Pro — $79/month, $790/year
  3. 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

  1. Go to Developers → Webhooks in Stripe Dashboard (make sure you're in Live mode)
  2. Click Add endpoint
  3. Set the URL to your backend endpoint:
https://YOUR_PROJECT_REF.supabase.co/functions/v1/stripe-webhook
https://YOUR_DEPLOYMENT.convex.site/stripe-webhook
  1. Select these events:
    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_succeeded
    • invoice.payment_failed
  2. Click Add endpoint
  3. 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 secret
npx convex env set STRIPE_SECRET_KEY sk_live_...
npx convex env set STRIPE_WEBHOOK_SECRET whsec_...   # ← the LIVE signing secret

6. 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 ModeLive Mode
Keyssk_test_... / pk_test_...sk_live_... / pk_live_...
Products/PricesCreated in test modeMust be recreated in live mode
Price IDsDifferentDifferent (must update code)
WebhookCLI forwarding or test endpointProduction endpoint on Supabase
Webhook SecretFrom CLI or test webhookFrom live webhook
CardsTest cards only (4242...)Real cards
MoneyNo real chargesReal charges
MCPCreates in test modeMust recreate in live mode

Next Steps

Done reading? Mark this page as complete.

On this page