Conversation
…s type Replace invitation status pgEnum with text() to avoid fragile coupling with Better Auth's values. Remove unused team/teamMember tables and session.activeTeamId (teams plugin not enabled). Add subscription table and stripeCustomerId columns for upcoming Stripe billing integration. Move team schema to docs/recipes/teams.md as an opt-in recipe.
Wire up @better-auth/stripe for subscription management with hosted Checkout. Server derives billing context from session (org vs personal). tRPC provides read-only subscription query; mutations go through the Better Auth client directly.
- Add comprehensive tests for billing router endpoints - Create Vitest config for API tests - Add billing queries tests for app - Update billing spec documentation
Stripe env vars are now optional — the app starts and works without them, billing endpoints simply return 404. This removes the setup barrier for contributors who don't need billing features.
Replaces inline spread-ternary with a stripePlugin() helper that encapsulates both the env guard and plugin configuration, keeping the betterAuth plugins array flat and scannable.
The `apps/*` glob matched `apps/email`, which has no vitest config but contains a generated `.react-email/` directory with its own vitest config and spec files, causing "describe is not defined" errors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrates Stripe billing using the
@better-auth/stripeplugin — customer lifecycle, subscription management, and webhook handling all managed by the auth layer.subscriptionschema, remove unusedteamtable, fix invitation status type@better-auth/stripeplugin with plan definitions, org-level billing authorization, and optional activation (works without Stripe env vars)billing.subscriptiontRPC query with TanStack Query integration (cache key includesactiveOrgIdfor automatic refetch on org switch)How it works
Mutations go through the Better Auth client (plugin handles Stripe API, session validation, org authorization). Reads go through tRPC for TanStack Query caching and batching.
Billing reference
The server derives
referenceIdfrom the session — org billing whenactiveOrganizationIdis set, personal billing otherwise. No client-side parameter needed.Key files
db/schema/subscription.tsapps/api/lib/plans.ts,apps/api/lib/stripe.tsapps/api/lib/auth.tsapps/api/routers/billing.tsapps/app/lib/queries/billing.tsapps/app/routes/(app)/settings.tsxdocs/specs/billing.mdPlan limits (single source of truth in
apps/api/lib/plans.ts)Stripe config is optional
All Stripe env vars are checked at startup — if any are missing, the plugin is not loaded. The app works normally without billing; endpoints simply don't exist.
Links