Application Configuration
LaunchKit uses a centralized configuration system to manage app settings, branding, integrations, and behavior. This guide covers all configuration options and customization possibilities.
Overview
Section titled “Overview”The main configuration file is located at /config.ts
and includes:
- App branding (name, description, domain)
- Payment settings (currency, Stripe configuration)
- Third-party integrations (Crisp, AWS, social links)
- Authentication flows (login/callback URLs)
- Theme and UI preferences
Core Configuration (/config.ts
)
Section titled “Core Configuration (/config.ts)”1. Basic App Settings
Section titled “1. Basic App Settings”const config = {
// REQUIRED: Your app's name (used throughout the UI)
appName: 'LaunchKit Project',
// REQUIRED: Short description for SEO and metadata
appDescription: 'The NextJS boilerplate with all you need to build your SaaS, AI tool, or any other web app.',
// REQUIRED: Your domain (no https://, no trailing slash)
domainName: 'localhost:3000', // Development
// domainName: 'yourawesomeapp.com', // Production
};
Usage in Components:
import config from '@/config';
// Page title
<title>{config.appName} - Dashboard</title>
// Meta description
<meta name="description" content={config.appDescription} />
// Redirect URLs
const redirectUrl = `https://${config.domainName}/dashboard`;
2. Customer Support Configuration
Section titled “2. Customer Support Configuration”const config = {
crisp: {
// Crisp website ID from your Crisp dashboard
id: 'your-crisp-website-id',
// Show Crisp only on specific routes
onlyShowOnRoutes: ['/'],
// If empty array, shows on all routes:
// onlyShowOnRoutes: [],
},
resend: {
// Support email (used when Crisp is not available)
supportEmail: '[email protected]',
},
};
How it works:
- If
crisp.id
is provided, the chat widget appears on specified routes - If no Crisp ID, the support system falls back to email
- The
ButtonSupport
component automatically handles the integration
const config = {
crisp: {
// Leave ID empty to disable Crisp
id: '',
},
resend: {
// REQUIRED when Crisp is disabled
supportEmail: '[email protected]',
},
};
Result: Support buttons will open email client instead of chat widget.
3. Payment and Currency Settings
Section titled “3. Payment and Currency Settings”const config = {
// Currency configuration
currency: {
// ISO 4217 currency code
code: 'USD', // 'EUR', 'GBP', 'CAD', etc.
// Currency symbol
symbol: '$', // '€', '£', 'C$', etc.
// Symbol position relative to amount
symbolPosition: 'before' as const, // 'before' or 'after'
},
stripe: {
// Products are now managed through the database
// This section is kept for future Stripe configuration
// Use /dashboard/admin/products to manage products
},
};
Usage in Components:
import config from '@/config';
// Format currency
const formatPrice = (amount: number) => {
const { symbol, symbolPosition } = config.currency;
const formatted = amount.toFixed(2);
return symbolPosition === 'before'
? `${symbol}${formatted}`
: `${formatted}${symbol}`;
};
// Example: formatPrice(99) → "$99.00"
4. Email Configuration
Section titled “4. Email Configuration”const config = {
resend: {
// Email 'From' field for automated emails
fromNoReply: `${config.appName} <[email protected]>`,
// Email 'From' field for personal emails
fromAdmin: `Your Name at ${config.appName} <[email protected]>`,
// Support email (shown to customers)
supportEmail: '[email protected]',
},
};
Email Template Usage:
// Emails automatically use these settings
await EmailService.sendPurchaseConfirmation({
// ... email data
// fromAdmin and supportEmail are automatically included
});
5. Authentication Configuration
Section titled “5. Authentication Configuration”const config = {
auth: {
// Login page URL
loginUrl: '/signin',
// Redirect after successful login
callbackUrl: '/dashboard',
},
};
Usage in Middleware:
// Redirect unauthenticated users
if (!user && isProtectedRoute) {
return NextResponse.redirect(new URL(config.auth.loginUrl, request.url));
}
// Redirect after successful auth
return NextResponse.redirect(new URL(config.auth.callbackUrl, request.url));
6. Theme Configuration
Section titled “6. Theme Configuration”const config = {
theme: {
// Default theme when app loads
defaultTheme: 'system', // 'light', 'dark', or 'system'
// Enable system theme detection
enableSystem: true,
// Disable transition animation on theme change
disableTransitionOnChange: true,
// Available themes (must match your CSS themes)
themes: ['light', 'dark', 'system'],
},
};
Theme Provider Usage:
// The theme provider automatically uses these settings
<ThemeProvider
defaultTheme={config.theme.defaultTheme}
enableSystem={config.theme.enableSystem}
disableTransitionOnChange={config.theme.disableTransitionOnChange}
themes={config.theme.themes}
>
{children}
</ThemeProvider>
7. Social Media Links
Section titled “7. Social Media Links”const config = {
social: {
// Discord server invite
discord: 'https://discord.gg/yourserver',
// Twitter/X profile
twitter: 'https://twitter.com/yourusername',
// GitHub organization/profile
github: 'https://github.com/yourusername',
// LinkedIn profile/company
linkedin: 'https://linkedin.com/company/yourcompany',
},
};
Footer Component Usage:
import config from '@/config';
const Footer = () => (
<footer>
<div className="social-links">
{config.social.twitter && (
<a href={config.social.twitter} target="_blank">
Twitter
</a>
)}
{config.social.github && (
<a href={config.social.github} target="_blank">
GitHub
</a>
)}
{/* More social links */}
</div>
</footer>
);
8. AWS/Cloud Storage Configuration
Section titled “8. AWS/Cloud Storage Configuration”const config = {
aws: {
// S3 bucket name
bucket: 'your-bucket-name',
// S3 bucket URL
bucketUrl: 'https://your-bucket-name.s3.amazonaws.com/',
// CloudFront CDN URL (optional)
cdn: 'https://d1234567890.cloudfront.net/',
},
};
File Upload Usage:
const uploadToS3 = async (file: File) => {
const uploadUrl = config.aws.cdn || config.aws.bucketUrl;
// Upload logic using the configured URLs
};
Environment-Specific Configuration
Section titled “Environment-Specific Configuration”1. Development vs Production
Section titled “1. Development vs Production”// config.ts
const isDevelopment = process.env.NODE_ENV === 'development';
const config = {
appName: 'LaunchKit Project',
// Different domains for different environments
domainName: isDevelopment
? 'localhost:3000'
: 'yourapp.com',
// Different support settings
crisp: {
id: isDevelopment
? '' // Disable in development
: 'your-production-crisp-id',
onlyShowOnRoutes: ['/'],
},
// Development-specific settings
...(isDevelopment && {
// Enable debugging features
debug: true,
// Show development tools
showDevTools: true,
}),
};
2. Feature Flags
Section titled “2. Feature Flags”const config = {
features: {
// Enable/disable features
enableBlog: true,
enableChat: true,
enableAnalytics: process.env.NODE_ENV === 'production',
enableEmailCapture: true,
// Beta features
betaFeatures: {
newDashboard: false,
advancedAnalytics: false,
},
},
};
Component Usage:
import config from '@/config';
const DashboardPage = () => {
return (
<div>
{config.features.enableAnalytics && <AnalyticsWidget />}
{config.features.betaFeatures.newDashboard && <NewDashboard />}
<StandardDashboard />
</div>
);
};
Advanced Configuration Patterns
Section titled “Advanced Configuration Patterns”1. Multi-Tenant Configuration
Section titled “1. Multi-Tenant Configuration”// For SaaS platforms with multiple customers
const config = {
multiTenant: {
enabled: true,
subdomainRouting: true, // customer.yourapp.com
customDomains: true, // customer-domain.com
},
// Tenant-specific overrides
getTenantConfig: (tenantId: string) => ({
appName: `${config.appName} - ${tenantId}`,
branding: {
primaryColor: getTenantColor(tenantId),
logo: getTenantLogo(tenantId),
},
}),
};
2. A/B Testing Configuration
Section titled “2. A/B Testing Configuration”const config = {
experiments: {
// Pricing page variants
pricingPageVariant: {
enabled: true,
variants: ['original', 'simplified', 'premium-focused'],
traffic: [50, 25, 25], // Percentage split
},
// CTA button tests
ctaButtonText: {
enabled: true,
variants: ['Get Started', 'Start Free Trial', 'Try Now'],
traffic: [33, 33, 34],
},
},
};
3. Integration Configuration
Section titled “3. Integration Configuration”const config = {
integrations: {
analytics: {
google: {
enabled: !!process.env.GOOGLE_ANALYTICS_ID,
id: process.env.GOOGLE_ANALYTICS_ID,
},
plausible: {
enabled: !!process.env.PLAUSIBLE_DOMAIN,
domain: process.env.PLAUSIBLE_DOMAIN,
},
},
monitoring: {
sentry: {
enabled: !!process.env.SENTRY_DSN,
dsn: process.env.SENTRY_DSN,
},
logRocket: {
enabled: !!process.env.LOGROCKET_APP_ID,
appId: process.env.LOGROCKET_APP_ID,
},
},
},
};
Configuration Validation
Section titled “Configuration Validation”1. Type Safety
Section titled “1. Type Safety”// types/config.ts
export interface ConfigProps {
appName: string;
appDescription: string;
domainName: string;
crisp: {
id: string;
onlyShowOnRoutes: string[];
};
currency: {
code: string;
symbol: string;
symbolPosition: 'before' | 'after';
};
theme: {
defaultTheme: 'light' | 'dark' | 'system';
enableSystem: boolean;
disableTransitionOnChange: boolean;
themes: string[];
};
// ... other config types
}
// config.ts
import { ConfigProps } from './types/config';
const config: ConfigProps = {
// Configuration with full type checking
};
2. Runtime Validation
Section titled “2. Runtime Validation”// utils/validateConfig.ts
import { z } from 'zod';
const configSchema = z.object({
appName: z.string().min(1, 'App name is required'),
domainName: z.string().min(1, 'Domain name is required'),
currency: z.object({
code: z.string().length(3, 'Currency code must be 3 characters'),
symbol: z.string().min(1, 'Currency symbol is required'),
symbolPosition: z.enum(['before', 'after']),
}),
});
export const validateConfig = (config: any) => {
try {
configSchema.parse(config);
return { valid: true, errors: [] };
} catch (error) {
return {
valid: false,
errors: error.errors.map(e => e.message)
};
}
};
// Use in your app
const validation = validateConfig(config);
if (!validation.valid) {
console.error('Configuration errors:', validation.errors);
}
Dynamic Configuration
Section titled “Dynamic Configuration”1. Database-Driven Settings
Section titled “1. Database-Driven Settings”// For settings that can be changed at runtime
interface AppSettings {
maintenance_mode: boolean;
allow_registrations: boolean;
max_file_size: number;
supported_currencies: string[];
}
const getAppSettings = async (): Promise<AppSettings> => {
const { data } = await supabase
.from('app_settings')
.select('*')
.single();
return data || defaultSettings;
};
// Usage in components
const useAppSettings = () => {
const [settings, setSettings] = useState<AppSettings | null>(null);
useEffect(() => {
getAppSettings().then(setSettings);
}, []);
return settings;
};
2. User Preferences
Section titled “2. User Preferences”interface UserPreferences {
theme: 'light' | 'dark' | 'system';
notifications: boolean;
language: string;
currency: string;
}
const getUserPreferences = async (userId: string): Promise<UserPreferences> => {
const { data } = await supabase
.from('user_preferences')
.select('*')
.eq('user_id', userId)
.single();
return data?.preferences || defaultPreferences;
};
Configuration Best Practices
Section titled “Configuration Best Practices”1. Environment Variables
Section titled “1. Environment Variables”Keep sensitive data in environment variables:
// config.ts
const config = {
// Public settings
appName: 'LaunchKit Project',
// Private settings (use environment variables)
stripe: {
publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
// Never put secret keys in config.ts
},
// Conditional settings
analytics: {
enabled: process.env.NODE_ENV === 'production',
trackingId: process.env.GOOGLE_ANALYTICS_ID,
},
};
// .env.local
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
2. Configuration Documentation
Section titled “2. Configuration Documentation”Document your configuration options:
/**
* Application Configuration
*
* This file contains all the configuration options for LaunchKit.
*
* REQUIRED SETTINGS:
* - appName: Your application name
* - domainName: Your domain (without https://)
* - resend.supportEmail: Support email address
*
* OPTIONAL SETTINGS:
* - crisp.id: Crisp chat widget ID
* - aws: AWS/S3 configuration for file uploads
* - social: Social media links for footer
*/
const config = {
// ... configuration
};
3. Configuration Testing
Section titled “3. Configuration Testing”// __tests__/config.test.ts
import config from '@/config';
describe('Configuration', () => {
test('has required fields', () => {
expect(config.appName).toBeDefined();
expect(config.domainName).toBeDefined();
expect(config.resend.supportEmail).toBeDefined();
});
test('currency format is valid', () => {
expect(['before', 'after']).toContain(config.currency.symbolPosition);
expect(config.currency.code).toHaveLength(3);
});
test('URLs are valid format', () => {
// Test social URLs
Object.values(config.social).forEach(url => {
if (url) {
expect(url).toMatch(/^https?:\/\//);
}
});
});
});
Troubleshooting Configuration Issues
Section titled “Troubleshooting Configuration Issues”Common Problems
Section titled “Common Problems”Configuration Not Loading:
// Debug configuration loading
console.log('Config loaded:', {
appName: config.appName,
domainName: config.domainName,
hasStripeKey: !!process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
});
Environment Variables Not Working:
# Check Next.js environment variable rules
# - NEXT_PUBLIC_ variables are available in browser
# - Regular variables only available on server
# .env.local
NEXT_PUBLIC_APP_NAME=MyApp # Available everywhere
STRIPE_SECRET_KEY=sk_... # Server-only
Type Errors:
// Ensure config matches ConfigProps interface
import { ConfigProps } from './types/config';
const config: ConfigProps = {
// TypeScript will catch missing or incorrect types
};
Next Steps
Section titled “Next Steps”Once your configuration is set up:
- Set up Development Workflow - Local development and hot reloading
- Test Your Configuration - Verify all settings work correctly
- Deploy to Production - Production configuration and environment variables
- Monitor Your App - Set up analytics and error tracking
Configuration Checklist
Section titled “Configuration Checklist”Before going to production, verify:
- App name and description are correct
- Domain name is set to production domain
- All required environment variables are set
- Currency and pricing are correct
- Email settings are configured and tested
- Support system (Crisp or email) is working
- Social media links are correct
- Theme settings match your brand
- Authentication URLs are correct
- All integrations are properly configured