Skip to main content

Stripe Setup

This project includes a complete Stripe subscription integration with a 7‑day free trial, webhook handling, and subscription‑gated routes.

What’s included

  • 7‑day free trial for all plans
  • Subscription state persisted in Firestore
  • Webhook handling for lifecycle events (created, updated, deleted, trial_will_end, invoice events)
  • Protected routes and components that require an active subscription or trial

1) Create products and prices

In the Stripe Dashboard:

  • Create a Basic plan (monthly) at $29 → record STRIPE_STARTER_PRICE_ID
  • Create a Pro plan (yearly) at $297 → record STRIPE_PRO_PRICE_ID

For each Price, add metadata:

  • credits_per_period: number of credits granted each billing period (e.g., 1000, 10000).
  • Optionally: use environment flag CREDITS_PRORATE_UPGRADES=true to enable immediate pro‑rated top‑ups on plan upgrades.

2) Configure environment variables

Create apps/web/.env.local with your real values:

# Firebase (client)
NEXT_PUBLIC_FIREBASE_API_KEY=your_firebase_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_firebase_app_id

# Stripe
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Price IDs created above
STRIPE_STARTER_PRICE_ID=price_...
STRIPE_PRO_PRICE_ID=price_...

# App
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secure-random-string

For production on Vercel, add these in the project’s Environment Variables (see Setup → Vercel Environment Variables).

3) Set up webhook endpoint

In Stripe Dashboard → Developers → Webhooks:

  • Add endpoint: your deployed Firebase Functions URL for stripeWebhook (e.g., https://us-central1-<project-id>.cloudfunctions.net/stripeWebhook or your Cloud Run URL if proxied)
  • Send events:
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • customer.subscription.trial_will_end
    • invoice.payment_succeeded
    • invoice.payment_failed
  • Copy the signing secret to Functions config or environment (STRIPE_WEBHOOK_SECRET)

Credits allocation is handled by the webhook on customer.subscription.created, invoice.payment_succeeded, and plan change logic on customer.subscription.updated.

4) Test the integration

  1. Start your app: pnpm dev
  2. Visit http://localhost:3000
  3. Start a free trial from the pricing page
  4. Use Stripe test card 4242 4242 4242 4242 with any future expiry

You should see the full flow: sign in, checkout, success redirect, and gated access depending on subscription status.

How it works

  • Pages: signup with plan selection, success page, subscription‑aware dashboard
  • API Routes: create checkout session, verify session
  • Webhook handler: Firebase Function stripeWebhook processes Stripe events
  • Components: SubscriptionGuard, inline subscription checks, enhanced AuthContext

Firestore schema

users/{userId}/subscription/current
{
customerId: "cus_...",
subscriptionId: "sub_...",
status: "trialing" | "active" | "canceled" | "past_due",
planId: "starter" | "pro",
currentPeriodStart: timestamp,
currentPeriodEnd: timestamp,
trialEnd: timestamp,
cancelAtPeriodEnd: boolean
}

Security notes

  • Webhook signature verification is required and implemented
  • Keep secret keys server‑side only; never expose to the client
  • Firestore rules should protect subscription data

Optional enhancements

  • Customer portal for managing billing
  • Trial ending email notifications
  • Subscription analytics
  • Promo codes and discounts