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=trueto 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/stripeWebhookor your Cloud Run URL if proxied) - Send events:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedcustomer.subscription.trial_will_endinvoice.payment_succeededinvoice.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
- Start your app:
pnpm dev - Visit
http://localhost:3000 - Start a free trial from the pricing page
- Use Stripe test card
4242 4242 4242 4242with 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
stripeWebhookprocesses Stripe events - Components:
SubscriptionGuard, inline subscription checks, enhancedAuthContext
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