Vibestacks LogoVibestacks
IntegrationsStripe & Payments

Payments & Subscription System

Understand how Vibestacks handles payments and subscriptions through Stripe and Better Auth integration. A complete overview of the architecture.

The application uses Stripe for payment processing, integrated through Better Auth's Stripe plugin. This provides a seamless connection between user authentication and subscription management.

Pricing Structure

Vibestacks comes with a flexible pricing structure that you can customize:

PlanPriceBillingTrial
Free$0--
Starter$19/monthMonthly/Annual-
Pro$49/monthMonthly/Annual14 days

Annual billing offers discounted rates compared to monthly pricing. All plans and pricing are configurable in config/app.ts.

How It Works

1. Customer Creation

When a user signs up, a Stripe customer is automatically created and linked to their account. This happens transparently during the registration process.

User Signs Up → Better Auth creates user → Stripe customer created → IDs linked

Automatic Linking

The createCustomerOnSignUp: true setting in your Stripe config handles this automatically. You don't need to write any code.

2. Subscription Flow

The subscription process follows this sequence:

┌─────────────────────────────────────────────────────────────────┐
│  1. User selects plan from pricing page                          │
│                          ↓                                       │
│  2. App creates Stripe Checkout session                          │
│                          ↓                                       │
│  3. User redirected to Stripe Checkout (secure payment)          │
│                          ↓                                       │
│  4. User completes payment                                       │
│                          ↓                                       │
│  5. Stripe sends webhook to your app                             │
│                          ↓                                       │
│  6. Better Auth processes webhook, creates subscription record   │
│                          ↓                                       │
│  7. User redirected back to app with active subscription         │
└─────────────────────────────────────────────────────────────────┘

The entire payment flow is handled by Stripe Checkout, meaning you never touch sensitive card data and don't need PCI compliance.

3. Subscription Management

Once subscribed, users can manage their subscription through multiple channels:

  • Upgrade - Move to a higher tier plan
  • Downgrade - Move to a lower tier plan
  • Cancel - End subscription (access continues until period end)
  • Update payment method - Change card via customer portal
  • View invoices - Access billing history

All management happens through Stripe's customer portal or your app's dashboard.

4. Trial Periods

Certain plans support free trial periods:

Trial Start → User has full plan access → Trial End → Convert to paid

                                          (or) Downgrade to free
  • Trial start and end dates are tracked automatically
  • Users are notified before trial expiration
  • One trial per user across all plans (prevents abuse)

Data Tracked

The subscription system tracks:

DataDescription
Plan nameWhich plan the user is on (free, starter, pro)
Stripe IDsCustomer ID, subscription ID, price ID
Statusactive, canceled, past_due, trialing, etc.
Billing periodCurrent period start and end dates
Trial datesTrial start/end (if applicable)
CancellationWhen and why (if canceled)

This data is stored in your database and kept in sync with Stripe via webhooks.

Subscription States

A subscription can be in several states:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  trialing   │ ──→ │   active    │ ──→ │  canceled   │
└─────────────┘     └─────────────┘     └─────────────┘


                    ┌─────────────┐
                    │  past_due   │
                    └─────────────┘


                    ┌─────────────┐
                    │  unpaid     │
                    └─────────────┘
StatusMeaning
trialingUser is in free trial period
activeSubscription is paid and active
past_duePayment failed, retrying
unpaidPayment failed after retries
canceledUser canceled (may still have access until period end)

Integration Points

The payment system connects to several parts of your application:

Authentication

Subscription status is tied to the authenticated user. When you fetch the current user, their subscription data is included:

const session = await auth.api.getSession();
const subscription = session?.user?.subscription;

Access Control

Plan limits can gate features throughout your app:

import { getPlan } from "@/config/app";

// Check if user can access a feature
const plan = getPlan(user.planName);
const canAccessFeature = plan?.limits.projects === -1 ||
                          userProjectCount < plan?.limits.projects;

Webhooks

Stripe events update subscription state in real-time:

EventAction
checkout.session.completedCreate subscription
customer.subscription.updatedUpdate plan/status
customer.subscription.deletedMark as canceled
invoice.payment_failedHandle failed payment

Security & Compliance

The architecture ensures security at every level:

  • No card data touches your servers - Stripe Checkout handles all payment info
  • PCI compliance handled by Stripe - You don't need certification
  • Webhook signature verification - Prevents spoofed events
  • Idempotent event processing - Handles duplicate webhooks safely

Your Responsibility

While Stripe handles payment security, you're still responsible for securing your application, protecting user data, and ensuring proper access control based on subscription status.

Architecture Diagram

┌─────────────────────────────────────────────────────────────────┐
│                        Your Application                          │
├──────────────────┬──────────────────┬───────────────────────────┤
│   Pricing Page   │    Dashboard     │      API Routes           │
│   └─ Plan cards  │    └─ Billing    │      └─ Feature gates     │
│   └─ Checkout    │    └─ Usage      │      └─ Limit checks      │
├──────────────────┴──────────────────┴───────────────────────────┤
│                     Better Auth + Stripe Plugin                  │
│   └─ subscription.upgrade()    └─ subscription.cancel()          │
│   └─ subscription.list()       └─ Webhook processing             │
├─────────────────────────────────────────────────────────────────┤
│                          Stripe API                              │
│   └─ Checkout Sessions         └─ Customer Portal                │
│   └─ Subscriptions             └─ Invoices                       │
│   └─ Webhooks                  └─ Payment Methods                │
└─────────────────────────────────────────────────────────────────┘

Summary

This architecture ensures:

  • Users always have accurate subscription status - Webhooks keep everything in sync
  • Stripe handles payment complexity - Billing, retries, receipts, tax
  • PCI compliance is not your problem - Stripe Checkout is fully compliant
  • Subscriptions are tied to auth - No separate user management needed

You focus on building features. Stripe and Better Auth handle the billing infrastructure.

Next Steps