Documentation
Documentation
Introduction

Getting Started

Getting started
Getting StartedInstallationQuick StartProject Structure

Configuration

Configuration
ConfigurationEnvironment ConfigurationEdge ConfigDatabaseAuth SecretStripeFirebaseStorageGoogle Maps And Cloud Service AccountOAuth ProvidersEmail DeliverySentryFeature Flags

Architecture

Architecture
Architecture OverviewTech StackoRPC MiddlewareDesign Principles

Patterns

Patterns
Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

Database
DatabaseSetupSchema DefinitionDatabase OperationsMigrationsCaching
Data Tables

API

oRPCProceduresRoutersoRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

Storage
StorageConfigurationUsageBuckets
Stripe Billing

Extra

Caching

Templates

Templates
Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate oRPC RouterAdd Translations

Development

Development
DevelopmentCommandsAI AgentsBest Practices
Pulling Updates

Stripe Billing

Setup and manage Stripe billing in the template

This guide explains how to set up and manage Stripe billing for the application.

Prerequisites

  • Stripe account (create one at stripe.com)
  • Stripe API keys configured in .env

Environment Variables

Add these to your .env file:

STRIPE_SECRET_KEY=sk_test_...       # From Stripe Dashboard > Developers > API keys
STRIPE_WEBHOOK_SECRET=whsec_...     # From webhook setup (see below)

Initial Setup

1. Create Stripe Products

Run the fixtures script to create Free and Pro plans in Stripe:

bun run stripe:fixtures

This creates:

  • Free Plan: $0/month, 3 members limit
  • Pro Plan: $29/month or $290/year, unlimited members

2. Sync Products to Database

  1. Start your app: bun run dev
  2. Navigate to /admin/configure-billing
  3. Click "Sync from Stripe" to import products

Local Development

Webhook Testing

For local testing, use Stripe CLI to forward webhooks:

# Install Stripe CLI (if not already)
brew install stripe/stripe-cli/stripe

# Login to Stripe
stripe login

# Forward webhooks to local server (all events)
bun run stripe:listen

# Equivalent direct command:
# stripe listen --forward-to localhost:3000/api/auth/stripe/webhook

Stripe Dashboard Webhook Events

When configuring the endpoint in Stripe Dashboard, select these events:

  • checkout.session.completed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted

These are the subscription lifecycle events handled by @better-auth/stripe in this project.

Copy the webhook signing secret (whsec_...) and add it to your .env:

STRIPE_WEBHOOK_SECRET=whsec_...

Testing Subscriptions

  1. Use Stripe's test card numbers:
    • Success: 4242 4242 4242 4242
    • Decline: 4000 0000 0000 0002
  2. Test subscription flows at /dashboard/billing (organization) or /settings/billing (user)

Architecture

Config Toggle

Billing is toggleable via src/config/app.ts:

Billing: {
  ORGANIZATION_BILLING: true,  // Enable billing for organizations
  USER_BILLING: false,          // Enable billing for individual users
  get ENABLED() {
    return this.ORGANIZATION_BILLING || this.USER_BILLING;
  },
},

When disabled:

  • Navigation items are hidden
  • Pages return notFound()
  • RPC mutation endpoints throw FORBIDDEN
  • Dashboard billing card is conditionally rendered

Plan Limits

Plans are stored in stripe_products table with limits in JSONB:

type PlanLimits = {
  members: number; // -1 for unlimited
};

Subscription Scopes

The system supports two subscription scopes:

  • User subscriptions: Personal plans at /settings/billing (controlled by Config.Billing.USER_BILLING)
  • Organization subscriptions: Team plans at /dashboard/billing (controlled by Config.Billing.ORGANIZATION_BILLING)

Both use referenceId to associate subscriptions with either a user ID or organization ID.

Members Limit Enforcement

The members limit tracks how many members an organization (or user scope) can have. Usage checking is done via the checkUsageLimitsByReferenceId function.

Product Data Source

/admin/configure-billing reads products from the local stripe_products table (cache), not directly from Stripe APIs on each page load.

To refresh prices/products after changing them in Stripe Dashboard:

  1. Open /admin/configure-billing
  2. Click "Sync from Stripe"

Note: current webhook handling is subscription-focused and does not auto-sync Stripe product/price catalog changes.

Admin Management

Access /admin/configure-billing to:

  • View all Stripe products
  • Sync products from Stripe
  • Monitor plan configuration

Customization

Adding New Plan Limits

  1. Update PlanLimits type in src/features/subscriptions/schema.ts
  2. Update stripe_products.limits JSONB structure
  3. Add enforcement logic where needed
  4. Update Stripe product metadata

Changing Prices

  1. Update prices in Stripe Dashboard
  2. Sync products at /admin/configure-billing
  3. New prices apply to new subscriptions only

Troubleshooting

Products Not Showing

  1. Verify STRIPE_SECRET_KEY is set correctly
  2. Check that products exist in Stripe Dashboard
  3. Run sync from /admin/configure-billing

Webhooks Not Working

  1. Verify STRIPE_WEBHOOK_SECRET matches CLI output
  2. Ensure Stripe CLI is running and forwarding
  3. Check server logs for webhook errors

Limit Not Enforcing

  1. Verify subscription exists for the reference
  2. Check stripe_products.limits has correct values
  3. Ensure sync was run after product changes
  4. Verify Config.Billing.ENABLED is true

On this page

Prerequisites
Environment Variables
Initial Setup
1. Create Stripe Products
2. Sync Products to Database
Local Development
Webhook Testing
Stripe Dashboard Webhook Events
Testing Subscriptions
Architecture
Config Toggle
Plan Limits
Subscription Scopes
Members Limit Enforcement
Product Data Source
Admin Management
Customization
Adding New Plan Limits
Changing Prices
Troubleshooting
Products Not Showing
Webhooks Not Working
Limit Not Enforcing