Stripe Customer Portal Setup

Date: 2025-01-04 Status: ✅ Code Complete - Ready for Testing

Overview

The Customer Portal is now implemented, allowing users to manage their subscriptions directly through Stripe's hosted portal. Users can change plans, update payment methods, cancel subscriptions, and view billing history.

Files Created

1. Customer Portal API Route

File: app/api/stripe/portal/route.ts

Creates Stripe Customer Portal sessions with:

  • Authentication check
  • Subscription lookup from Convex
  • Return URL to settings page
  • Error handling

2. Manage Subscription Button Component

File: components/manage-subscription-button.tsx

Reusable button that:

  • Calls portal API
  • Shows loading state
  • Redirects to Stripe portal
  • Handles errors gracefully
  • Includes external link icon

3. Subscription Status Card Component

File: components/subscription-status-card.tsx

Comprehensive subscription display showing:

  • Current tier and status
  • Trial information (days remaining)
  • Plan limits (pages, tabs, features)
  • Status badges (Active, Trial, Past Due, Canceled)
  • Manage subscription button
  • Upgrade link for free tier users

4. Settings Page

File: app/settings/page.tsx

Simple settings page with:

  • Subscription status card
  • Clean layout
  • Placeholder for future settings sections

What Users Can Do in Customer Portal

Subscription Management

  • Upgrade/Downgrade Plans - Switch between Personal, Pro, Team
  • Change Billing Cycle - Switch between monthly and yearly
  • Cancel Subscription - Cancel at period end or immediately
  • Reactivate Canceled - Resume canceled subscriptions

Payment Methods

  • Update Card - Change payment method
  • Add Multiple Cards - Store multiple payment methods
  • Set Default - Choose default payment method

Billing History

  • View Invoices - See all past invoices
  • Download PDFs - Download invoice PDFs
  • View Upcoming - See upcoming invoice amounts

How It Works

User Flow

  1. User goes to /settings
  2. Subscription Status Card displays:
    • Current tier
    • Status (Active, Trial, Past Due, etc.)
    • Days remaining in trial (if applicable)
    • Plan limits
  3. User clicks "Manage Subscription"
  4. API creates portal session:
    • Looks up subscription in Convex
    • Gets Stripe customer ID
    • Creates portal session with return URL
  5. User redirected to Stripe Customer Portal
  6. User makes changes (upgrade, cancel, update card, etc.)
  7. Stripe sends webhooks (already configured)
  8. Webhooks update Convex (already implemented)
  9. User clicks "Return"
  10. Redirected back to /settings?portal=true

API Request Format

POST /api/stripe/portal
Content-Type: application/json

{} // Empty body - user ID from authentication

API Response Format

{
  "url": "https://billing.stripe.com/p/session/..."
}

Stripe Portal Configuration

The Customer Portal is automatically configured with Stripe's default settings. To customize:

  1. Go to Stripe DashboardSettingsCustomer Portal
  2. Configure portal settings:
    • Subscription cancellation: Allow customers to cancel
    • Plan changes: Allow customers to change plans
    • Payment method updates: Allow customers to update cards
    • Invoice history: Show invoice history
    • Promo codes: Allow promo code redemption
✅ Allow customers to cancel subscriptions
✅ Allow customers to switch plans
✅ Allow customers to update payment methods
✅ Show invoice history
✅ Allow promo code redemption during plan changes
✅ Require confirmation before canceling

Testing the Customer Portal

Prerequisites

  1. Have an active subscription (created via checkout flow)
  2. Be signed in to the app
  3. Environment variables set (from previous setups)

Test Steps

  1. Complete a checkout (use test card 4242 4242 4242 4242)
  2. Go to /settings in your app
  3. Verify Subscription Status Card shows:
    • Correct tier (Personal, Pro, or Team)
    • Status badge (Active or Trial)
    • Trial days remaining (if in trial)
    • Plan limits
  4. Click "Manage Subscription"
  5. Verify redirect to Stripe Customer Portal
  6. In portal, try:
    • Viewing invoice history
    • Updating payment method (use another test card)
    • Changing plan (upgrade/downgrade)
    • Canceling subscription
  7. Click "Return to [your app]"
  8. Verify redirect back to /settings
  9. Check subscription status updated (may take a moment for webhook)

Test Scenarios

Scenario 1: Upgrade Plan

  1. Subscribe to Personal tier
  2. Go to settings → Manage Subscription
  3. In portal, upgrade to Pro tier
  4. Return to app
  5. Verify status card shows Pro tier

Scenario 2: Update Payment Method

  1. Have an active subscription
  2. Go to settings → Manage Subscription
  3. In portal, click "Update payment method"
  4. Add new test card: 5555 5555 5555 4444
  5. Set as default
  6. Return to app

Scenario 3: Cancel Subscription

  1. Have an active subscription
  2. Go to settings → Manage Subscription
  3. In portal, click "Cancel subscription"
  4. Choose "Cancel at end of period"
  5. Return to app
  6. Verify status card shows cancellation notice

Scenario 4: Reactivate Canceled

  1. Have a canceled subscription (pending end of period)
  2. Go to settings → Manage Subscription
  3. In portal, click "Renew subscription"
  4. Return to app
  5. Verify status card shows active again

Status Badge Indicators

The Subscription Status Card displays different badges based on subscription status:

StatusBadgeMeaning
active🟢 ActiveSubscription is active and paid
trialing🔵 Trial ActiveCurrently in free trial period
past_due🟡 Payment DuePayment failed, needs attention
canceled⚪ CanceledSubscription is canceled
incomplete⚪ IncompletePayment incomplete

Common Issues

"No subscription found" Error

Cause: User hasn't subscribed yet

Expected Behavior: Portal button should only show for subscribed users

Fix: The Subscription Status Card hides the manage button for free tier users and shows "View Plans" instead

"No Stripe customer ID found" Error

Cause: Subscription record missing Stripe customer ID

Should not happen with current implementation - checkout flow includes customer ID

If it happens: Check webhook logs to ensure customer.subscription.created was processed correctly

Portal Shows Wrong Information

Cause: Webhook not processed or Convex data out of sync

Fix:

  1. Check webhook logs for errors
  2. Verify webhook was received (check ngrok or Stripe dashboard)
  3. Check Convex database for subscription record
  4. Manually trigger webhook test from Stripe dashboard

Return URL Not Working

Cause: Base URL not configured correctly

Fix: Set NEXT_PUBLIC_BASE_URL in .env.local:

NEXT_PUBLIC_BASE_URL=http://localhost:3017

Or for production:

NEXT_PUBLIC_BASE_URL=https://homepage.dev

Security Notes

  • ✅ Authentication required (Clerk auth)
  • ✅ User can only access their own subscription
  • ✅ Stripe handles all payment processing
  • ✅ Customer ID verified from Convex database
  • ✅ Portal sessions expire after use
  • ✅ Return URL validated by Stripe

Integration with Existing Features

Phase 1: Backend Tier Enforcement

  • ✅ Limits enforced when creating pages/tabs
  • ✅ Users blocked from exceeding limits
  • ✅ Clear error messages with upgrade suggestions

Phase 2: Webhooks

  • ✅ Subscription changes sync automatically
  • ✅ Plan upgrades/downgrades reflected immediately
  • ✅ Cancellations update status in Convex

Customer Portal (This Feature)

  • ✅ Users can self-serve subscription management
  • ✅ No support tickets needed for common tasks
  • ✅ Seamless experience staying in Stripe's UI

Next Steps

After Customer Portal is tested:

  1. Frontend Usage Indicators

    • Show usage vs limits on dashboard
    • Display progress bars
    • Add usage badges
  2. Upgrade Prompts

    • Modal when hitting limits
    • Inline upgrade CTAs
    • Trial countdown reminders
  3. Email Notifications

    • Trial ending reminders
    • Payment failed notices
    • Subscription change confirmations
  4. Switch to Production

    • Use live Stripe keys
    • Update webhook to production URL
    • Test with real cards (small amounts)

Reference Documents:

  • docs/STRIPE_PRODUCT_SETUP.md - Product and price IDs
  • docs/STRIPE_WEBHOOK_SETUP.md - Webhook configuration
  • docs/STRIPE_CHECKOUT_SETUP.md - Checkout flow
  • docs/PHASE_1_IMPLEMENTATION_COMPLETE.md - Backend tier enforcement
  • docs/TIER_MANAGEMENT_PLAN.md - Complete implementation roadmap

On this page