LogoLaunchSaaS

Provider Configuration

Configure which email, payment, cache, storage, newsletter and cron providers your app uses via capabilities.ts

LaunchSaaS no longer uses a shared features config file.

The current model is:

  • package defines contracts
  • app builds concrete instances
  • components are enabled by usage, not by global flags

Where Configuration Lives

AreaContract lives inApp instance lives in
AuthBetter Auth + app-local wiringapps/launchsaas/src/lib/auth/
Payment product catalogapps/launchsaas/src/configuration/product/apps/launchsaas/src/configuration/product/
Provider wiringpackage provider interfacesapps/launchsaas/src/capabilities.ts
Cookie consent UIcomponent propsrender CookieBanner where needed

Auth Configuration

Auth is wired directly in apps/launchsaas/src/lib/auth/:

  • auth.ts constructs the Better Auth server instance
  • auth-client.ts constructs the Better Auth client
  • OAuth buttons appear when the matching public client IDs exist
  • CAPTCHA is enabled when both CAPTCHA_SECRET_KEY and NEXT_PUBLIC_CAPTCHA_PUBLIC_KEY are set

Payment Product Configuration

Product catalog types and lookup helpers are fully app-owned:

// apps/launchsaas/src/configuration/product/products.ts
import type { Product } from "./types";

export const products: Product[] = [
  {
    id: "price_123",
    name: "Lifetime Access",
    provider: "stripe",
    type: "onetime",
    sandbox: false,
  },
];

@launchsaas/payment still owns checkout-related types such as CustomField and ProductType, but the catalog itself now lives entirely in apps/launchsaas/src/configuration/product/. A small helper in index.ts chooses the pricing page product by ID.

Provider Wiring

Choosing which email, payment, cache, newsletter, storage, or cron provider is active happens in:

// apps/launchsaas/src/capabilities.ts
export const capabilities = {
  email: ResendEmailProvider.create(),
  // Swap for any supported payment provider:
  // StripePaymentProvider, CreemPaymentProvider, PolarPaymentProvider,
  // DodoPaymentProvider, LemonSqueezyPaymentProvider
  payment: StripePaymentProvider.create(new AppPaymentEventHandler()),
  cache: null,
  storage: null,
  newsletter: null,
  cron: null,
};

There is no global features.payment.provider switch anymore.

Cookie consent is not configured globally.

  • Render CookieBanner if you want consent UI.
  • Pass requireCookieConsent to Analytics if analytics should wait for consent.
  • Remove either component if you do not need that behavior.
<CookieBanner position="bottom-left" />
<Analytics requireCookieConsent />

Guidance

  • Put concrete runtime config in the app.
  • Put reusable contracts and types in packages.
  • Do not add another shared feature-flag layer for auth, payment, or cookie consent.