Features Configuration
Centralized feature configuration and modular architecture
Features Configuration
LaunchSaaS uses a centralized feature configuration system that allows you to easily enable, disable, or switch between different service providers without modifying environment variables or code throughout your application.
Configuration File
All feature configurations are managed in src/configuration/features.ts:
import { Features } from "@/schemas/site-configuration";
export const features: Features = {
email: {
provider: "resend",
},
newsletter: {
provider: "resend",
},
storage: {
provider: "disabled",
},
authentication: {
magicLink: true,
captcha: {
enabled: true,
provider: "cloudflare-turnstile",
},
oauths: {
google: true,
github: true,
},
},
payment: {
provider: "stripe",
hooks: {
github: true,
email: true,
},
},
};Feature Modules
Configure email service providers for transactional emails.
Available Providers:
resend- Resend email servicedisabled- No-op provider (logs to console)
Configuration:
email: {
provider: "resend", // or "disabled"
}Learn more: Email Documentation
Newsletter
Configure newsletter service providers for managing subscriptions.
Available Providers:
resend- Resend Audiencesdisabled- No-op provider (logs to console)
Configuration:
newsletter: {
provider: "resend", // or "disabled"
}Learn more: Newsletter Documentation
Storage
Configure storage providers for file uploads.
Available Providers:
s3- S3-compatible storage (AWS S3, Cloudflare R2, MinIO)disabled- No-op provider (logs to console)
Configuration:
storage: {
provider: "s3", // or "disabled"
}Learn more: Storage Documentation
Payment
Configure payment providers and post-payment hooks.
Available Providers:
stripe- Stripe paymentscreem- Creem paymentsdisabled- No-op provider (logs to console)
Configuration:
payment: {
provider: "stripe", // "stripe" | "creem" | "disabled"
hooks: {
github: true, // Enable GitHub repository access
email: true, // Enable payment confirmation emails
},
}Payment Hooks
Payment hooks allow you to run custom logic after payment completion:
github- Automatically adds customers as GitHub collaboratorsemail- Sends payment confirmation emails
Learn more: Payment Documentation
Authentication
Configure authentication methods and providers.
Configuration:
authentication: {
magicLink: true, // Enable passwordless login
captcha: {
enabled: true,
provider: "cloudflare-turnstile", // or "hcaptcha", "captchafox"
},
oauths: {
google: true, // Enable Google OAuth
github: true, // Enable GitHub OAuth
},
}Learn more: Authentication Documentation
Architecture Benefits
1. Centralized Configuration
All feature toggles are in one place, making it easy to see what's enabled at a glance.
2. Provider Flexibility
Switch between providers by changing a single configuration value:
// Switch from Stripe to Creem
payment: {
provider: "creem", // Changed from "stripe"
}3. Factory Pattern
Each module uses a factory pattern to instantiate the correct provider:
// Example: Email Provider Factory
export class EmailProviderFactory {
static getProvider(): Provider {
const type = features.email.provider;
switch (type) {
case "resend":
return ResendProvider.create();
case "disabled":
return new NoOpEmailProvider();
}
}
}4. No-Op Providers
When a feature is disabled, a no-op provider is used that:
- Logs operations to console (for debugging)
- Doesn't require environment variables
- Allows development without external services
5. Type Safety
The Features type ensures compile-time validation:
export interface Features {
email: {
provider: "resend" | "disabled";
};
newsletter: {
provider: "resend" | "disabled";
};
storage: {
provider: "s3" | "disabled";
};
payment: {
provider: "stripe" | "creem" | "disabled";
hooks: {
github: boolean;
email: boolean;
};
};
authentication: {
magicLink: boolean;
captcha: {
enabled: boolean;
provider: "cloudflare-turnstile" | "hcaptcha" | "captchafox";
};
oauths: {
google: boolean;
github: boolean;
};
};
}Adding Custom Providers
To add a custom provider to any module:
1. Implement Provider Interface
Create a new provider class implementing the module's provider interface:
// Example: Custom email provider
export class CustomEmailProvider implements Provider {
async sendEmail(options: SendEmailOptions): Promise<SendEmailResult> {
// Your implementation
}
}2. Register in Factory
Add your provider to the factory:
// In src/lib/email/factory.ts
case "custom":
return new CustomEmailProvider();3. Update Type Definitions
Add your provider to the Features type:
// In src/schemas/site-configuration.ts
email: {
provider: "resend" | "custom" | "disabled";
}4. Configure
Enable your custom provider:
// In src/configuration/features.ts
email: {
provider: "custom",
}Best Practices
Development vs Production
Use different configurations for different environments:
const isDevelopment = process.env.NEXT_PUBLIC_APP_ENV === "local";
export const features: Features = {
email: {
provider: isDevelopment ? "disabled" : "resend",
},
// ... other features
};Feature Flags
Use the configuration for feature flags:
// Check if a feature is enabled
if (features.payment.hooks.github) {
// GitHub integration logic
}Environment Validation
Providers validate required environment variables at startup:
export class ResendProvider implements Provider {
constructor() {
if (!env.RESEND_API_KEY) {
throw new Error("RESEND_API_KEY is required");
}
}
}This ensures you catch configuration errors early.
References
- Email Configuration
- Newsletter Configuration
- Storage Configuration
- Payment Configuration
- Authentication Configuration