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
| Area | Contract lives in | App instance lives in |
|---|---|---|
| Auth | Better Auth + app-local wiring | apps/launchsaas/src/lib/auth/ |
| Payment product catalog | apps/launchsaas/src/configuration/product/ | apps/launchsaas/src/configuration/product/ |
| Provider wiring | package provider interfaces | apps/launchsaas/src/capabilities.ts |
| Cookie consent UI | component props | render CookieBanner where needed |
Auth Configuration
Auth is wired directly in apps/launchsaas/src/lib/auth/:
auth.tsconstructs the Better Auth server instanceauth-client.tsconstructs the Better Auth client- OAuth buttons appear when the matching public client IDs exist
- CAPTCHA is enabled when both
CAPTCHA_SECRET_KEYandNEXT_PUBLIC_CAPTCHA_PUBLIC_KEYare 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
Cookie consent is not configured globally.
- Render
CookieBannerif you want consent UI. - Pass
requireCookieConsenttoAnalyticsif 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.