Spacerr
  • Features
  • Pricing
  • FAQ
  • Docs
Get Access
Spacerr
  • Introduction
  • Features
  • Tech Stack
  • Setup
  • Configuration
  • Agents
  • Database
  • Jobs
  • Admin
  • Settings
  • Billing
  • Storage
  • Email
  • Support
  • Localization
  • SEO
  • Analytics
  • UI And Navigation
  • Deploying To Production
  • Testing And QA
  • Troubleshooting

Search documentation

Search documentation pages.

Documentation/Billing

Billing

Spacerr includes Stripe checkout examples for monthly subscriptions, yearly subscriptions, and one time payments. These are examples, not fixed rules. You can change the products, price IDs, plan names, access rules, and pricing UI to fit your own SaaS model.

What It Includes

The billing layer includes:

  • Stripe checkout session creation.
  • Server fetched Stripe prices.
  • Monthly subscription examples.
  • Yearly subscription examples.
  • One time payment examples.
  • Post checkout dashboard handling.
  • Stripe webhook handling through Better Auth.
  • Paid access tracking.
  • Billing status APIs.
  • Public pricing UI.

Price IDs

Create prices in Stripe, then place the IDs in your environment file.

txt
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID_MONTHLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_YEARLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_ONE_TIME="price_..."

The starter uses Stripe Price objects as the source of truth. Use Price IDs that start with price_, not Stripe Product IDs that start with prod_. That means pricing displayed in the UI can come from Stripe instead of being hardcoded in React components.

Important Files

Billing code lives in src/features/billing.

txt
src/features/billing
  api
  components
  constants
  hooks
  lib
  repositories
  schemas
  types
  utils

Start with these files:

  • src/features/billing/schemas/create-checkout-session.schema.ts for allowed checkout products.
  • src/features/billing/utils/get-stripe-price-id.utils.ts for mapping product choices to Stripe price IDs.
  • src/features/billing/repositories/billing-products.repository.ts for loading Stripe product and price data.
  • src/features/billing/utils/create-checkout-session-url.server.ts for checkout session creation.
  • src/features/billing/utils/get-kit-access.server.ts for paid access checks.
  • src/components/product/pricing.section.tsx for the public pricing section.

Checkout Flow

The default checkout behavior is simple:

  1. The user chooses a monthly, yearly, or one time product.
  2. The server checks whether the user already has access.
  3. If the user already bought that product, the product stays visible as owned and checkout is not created again.
  4. If the user does not have access yet, the server creates a Stripe checkout session.
  5. After checkout, Stripe sends the user back to the dashboard.
  6. Stripe webhooks update the user's access state.
  7. The dashboard shows what the user owns so they do not rebuy the same product.

Always keep the final access check on the server. The UI can show owned products, but server code decides whether checkout should start.

Webhooks

Local webhook testing uses the Stripe CLI.

bash
stripe login
bun stripe:listen

The listener forwards events to the Better Auth Stripe webhook route.

typescript
localhost:3000/api/auth/stripe/webhook

For production, add the production webhook endpoint in Stripe and copy the live webhook signing secret into your production environment.

txt
https://your-domain.com/api/auth/stripe/webhook

Changing Pricing

You can build almost any pricing model from the included examples.

For a subscription SaaS:

  1. Create monthly and yearly recurring prices in Stripe.
  2. Add their price IDs to env vars.
  3. Map plan choices to the right Stripe prices.
  4. Track active subscription access after webhook events.
  5. Update the pricing section copy and plan cards.

For lifetime access or downloadable products:

  1. Create one time prices in Stripe.
  2. Map product choices to one time price IDs.
  3. Track permanent access after successful checkout.
  4. Update the pricing section and post purchase experience.

The examples are intentionally small so you can reshape them quickly. You are not locked into the default plan names, access fields, or checkout products.

Access State

The starter stores permanent one time purchase access on the user record and reads active subscription access from Stripe by customer ID. The admin docs show how to present that as one clear access status for operators.

Keep access checks server side. UI state can make the product feel responsive, but route handlers and server utilities decide whether a user can access paid features.

Launch Checklist

Before charging real users:

  • Switch Stripe from test mode to live mode.
  • Use the live Stripe secret key.
  • Create live monthly, yearly, and one time prices.
  • Add the live webhook endpoint.
  • Copy the live webhook signing secret.
  • Run a real checkout with a small internal test product or Stripe test tools.
  • Confirm the dashboard return, dashboard access, admin status, and webhook logs.
Settings

Learn how account settings, profile details, notifications, appearance, language, and legal links are structured.

AI Workspace

Learn what the AI workspace includes and where each part lives.

On this page
What It IncludesPrice IDsImportant FilesCheckout FlowWebhooksChanging PricingAccess StateLaunch Checklist