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:
| Plan | Price | Billing | Trial |
|---|---|---|---|
| Free | $0 | - | - |
| Starter | $19/month | Monthly/Annual | - |
| Pro | $49/month | Monthly/Annual | 14 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 linkedAutomatic 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:
| Data | Description |
|---|---|
| Plan name | Which plan the user is on (free, starter, pro) |
| Stripe IDs | Customer ID, subscription ID, price ID |
| Status | active, canceled, past_due, trialing, etc. |
| Billing period | Current period start and end dates |
| Trial dates | Trial start/end (if applicable) |
| Cancellation | When 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 │
└─────────────┘| Status | Meaning |
|---|---|
trialing | User is in free trial period |
active | Subscription is paid and active |
past_due | Payment failed, retrying |
unpaid | Payment failed after retries |
canceled | User 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:
| Event | Action |
|---|---|
checkout.session.completed | Create subscription |
customer.subscription.updated | Update plan/status |
customer.subscription.deleted | Mark as canceled |
invoice.payment_failed | Handle 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
- Configuration - Set up your Stripe API keys
- Plans & Pricing - Configure your subscription tiers
- Webhooks - Understand event processing
- Trials - Set up free trial periods
- Billing Portal - Let users manage subscriptions
Stripe Overview
Learn how Vibestacks integrates with Stripe for subscription billing. Understand the architecture, what's included, and how to get started.
Configuration
Set up Stripe API keys, webhook secrets, and configure the Stripe integration in Vibestacks. Step-by-step guide for test and production environments.