Codapult's behavior is controlled through a small set of TypeScript configuration files. These are the files you'll edit most when making the product your own.
| File | Purpose |
| -------------------------- | ---------------------------------------------------------------- |
| src/config/app.ts | Brand, feature toggles, auth options, AI settings |
| src/config/navigation.ts | Dashboard and admin sidebar items |
| src/config/marketing.ts | Landing page pricing, testimonials, stats, competitor comparison |
| src/lib/config.ts | Typed env var access (auto-generated — don't edit) |
Brand configuration
Edit src/config/app.ts to set your product identity:
export const appConfig: AppConfig = {
brand: {
name: 'MyApp',
description: 'The best project management tool for teams',
logo: '/logo.svg',
favicon: '/favicon.ico',
url: 'https://myapp.com',
supportEmail: '[email protected]',
},
// ...
};
These values are used in the sidebar, email templates, SEO meta tags, and OG images throughout the app.
Feature toggles
The features object controls which modules are active. Set any toggle to false to disable a feature — it will be hidden from the navigation, and its routes become inaccessible.
features: {
aiChat: true,
teams: true,
blog: true,
helpCenter: true,
waitlist: true,
referrals: true,
analytics: true,
workflows: true,
webhooks: true,
auditLog: true,
reports: true,
featureRequests: true,
changelog: true,
onboarding: true,
branding: true,
sso: true,
experiments: true,
dripCampaigns: true,
},
All 18 toggles are true by default. Here's what each one controls:
| Toggle | Feature |
| ----------------- | ---------------------------------------------- |
| aiChat | AI chat assistant (Vercel AI SDK, streaming) |
| teams | Organizations, multi-tenancy, team invitations |
| blog | MDX blog with i18n, tags, and authors |
| helpCenter | Help center / documentation (MDX) |
| waitlist | Waitlist with email confirmation |
| referrals | Referral / affiliate program |
| analytics | Self-serve analytics dashboard |
| workflows | Event-triggered workflow automation |
| webhooks | Outgoing webhooks (HMAC signed) |
| auditLog | User-facing activity / audit log |
| reports | Scheduled email reports |
| featureRequests | Public feature request voting board |
| changelog | In-app "What's new" changelog widget |
| onboarding | Interactive onboarding tours |
| branding | Per-org white-labeling |
| sso | Enterprise SSO (SAML via BoxyHQ) |
| experiments | A/B testing framework |
| dripCampaigns | Email drip campaigns |
Navigation items are automatically hidden when their linked feature is disabled — no manual sidebar editing needed.
Auth configuration
Control which sign-in methods appear on the auth pages:
auth: {
oauthProviders: ['google', 'github'],
magicLink: true,
passkeys: true,
twoFactor: true,
},
| Property | Type | Description |
| ---------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
| oauthProviders | OAuthProvider[] | OAuth buttons shown on sign-in/sign-up. Options: 'google', 'github', 'apple', 'discord', 'twitter', 'microsoft' |
| magicLink | boolean | Passwordless email sign-in via magic link |
| passkeys | boolean | WebAuthn / passkey authentication |
| twoFactor | boolean | TOTP-based two-factor authentication |
You still need to configure the corresponding environment variables (e.g. GOOGLE_CLIENT_ID) for OAuth providers to function.
AI configuration
Customize the AI chat assistant behavior:
ai: {
defaultModel: 'gpt-4o-mini',
systemPrompt: 'You are a helpful AI assistant. Be concise, accurate, and helpful.',
ragEnabled: true,
ragMaxChunks: 3,
ragMinScore: 0.4,
allowedModels: [],
},
| Property | Type | Description |
| --------------- | ---------- | ---------------------------------------------------------------------------------- |
| defaultModel | string | Default model ID. Must match an entry in src/lib/ai/models.ts |
| systemPrompt | string | System prompt prepended to every conversation |
| ragEnabled | boolean | Enable retrieval-augmented generation in chat |
| ragMaxChunks | number | Maximum context chunks injected from RAG |
| ragMinScore | number | Minimum cosine similarity score for RAG results (0–1) |
| allowedModels | string[] | Models shown in the chat model selector. Empty array = all models from models.ts |
Navigation
Edit src/config/navigation.ts to customize sidebar items for the dashboard and admin panel.
Each item has a href, label, icon (from Lucide), and an optional featureKey:
import type { FeaturesConfig } from './app';
export interface NavItem {
href: string;
label: string;
icon: LucideIcon;
featureKey?: keyof FeaturesConfig;
}
When featureKey is set, the item is automatically hidden if that feature is disabled in appConfig.features.
Dashboard sidebar
export const dashboardNavItems: NavItem[] = [
{ href: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
{ href: '/dashboard/ai-chat', label: 'AI Chat', icon: MessageSquare, featureKey: 'aiChat' },
{ href: '/dashboard/analytics', label: 'Analytics', icon: BarChart3, featureKey: 'analytics' },
{ href: '/dashboard/billing', label: 'Billing', icon: CreditCard },
// ...add your own items here
];
Admin sidebar
export const adminNavItems: NavItem[] = [
{ href: '/admin', label: 'Overview', icon: LayoutDashboard },
{ href: '/admin/users', label: 'Users', icon: Users },
{ href: '/admin/subscriptions', label: 'Subscriptions', icon: CreditCard },
{ href: '/admin/feature-flags', label: 'Feature Flags', icon: Flag },
// ...
];
To add a custom page, create the route in src/app/(dashboard)/dashboard/your-page/page.tsx and add a corresponding entry to dashboardNavItems.
Marketing configuration
Edit src/config/marketing.ts to customize the landing page content.
Pricing tiers
export const pricingTiers: PricingTier[] = [
{
key: 'starter',
price: '$49',
featureKeys: ['tierFeatureFullCode', 'tierFeatureAllModules', 'tierFeatureProject1'],
},
{
key: 'pro',
price: '$99',
featured: true,
featureKeys: ['tierFeatureFullCode', 'tierFeatureAllModules', 'tierFeatureProject3'],
},
{
key: 'enterprise',
price: '$149',
featureKeys: ['tierFeatureFullCode', 'tierFeatureAllModules', 'tierFeatureProjectUnlimited'],
},
];
Feature labels are stored in messages/en.json under the "Pricing" namespace, so they support i18n. The key maps to a translation key for the tier name.
Set featured: true on a tier to visually highlight it. Use the optional href property to link to an external checkout (e.g. LemonSqueezy or Gumroad).
Testimonials
export const testimonials: Testimonial[] = [
{
name: 'Alex Chen',
role: 'Founder, StartupXYZ',
content: 'Codapult saved me weeks of setup time.',
initials: 'AC',
},
// ...add real customer quotes
];
Stats and competitor comparison
The stats array powers the "by the numbers" section on the landing page. The comparisonFeatures array generates the competitor comparison table — edit it to reflect your product's feature matrix.
Typed env var access
src/lib/config.ts provides a typed env object for reading environment variables in server code:
import { env } from '@/lib/config';
// Type-safe access with defaults
env.authProvider; // 'better-auth' | 'kinde'
env.paymentProvider; // 'stripe' | 'lemonsqueezy'
env.turso.url; // string
env.stripe.secretKey; // string
env.notificationTransport; // 'poll' | 'sse' | 'ws'
This file is auto-generated based on .env.example. You don't need to edit it unless you add a new environment variable — in that case, add a corresponding entry to the env object.
For the full list of environment variables and their descriptions, see the Environment Variables reference.