Configuration
Central config.ts is the single source of truth. App settings, billing plans, appearance, auth, admin, SEO.
Why one config file
Every customization point that matters lives in config.ts at the project root. App name, billing plans, appearance, auth providers, admin emails, SEO defaults: one file, typed against config.types.ts, no scattered constants to hunt through. Edit this and the rest of the template adapts.
The default config.ts ships with SecureStartKit's actual production values as a worked example. Replace them with your own.
App settings
appName: 'YourSaaS',
appDescription: 'Your one-line SEO description.',
domainName: 'yoursaas.com', // No https://, no trailing slash
domainName is used in canonical URLs, the sitemap, structured data, and email templates. Keep it bare (no protocol, no trailing slash).
Billing plans
billing: {
provider: 'stripe',
plans: [
{
name: 'Starter',
description: 'A short value-prop sentence.',
price: { monthly: 199, yearly: 199 },
priceAnchor: { monthly: 249, yearly: 249 }, // Optional: shows a crossed-out price
priceId: {
monthly: 'price_xxx', // From Stripe Dashboard
yearly: 'price_xxx',
},
features: ['Feature 1', 'Feature 2'],
},
{
name: 'Pro',
description: '...',
price: { monthly: 249, yearly: 249 },
priceId: {
monthly: 'price_xxx',
yearly: 'price_xxx',
},
isFeatured: true, // Highlights as "Most Popular"
features: ['Everything in Starter', '...'],
},
],
}
Three properties worth knowing:
priceAnchoris optional. Setting it renders a crossed-out anchor price next to the real price, which signals discount framing.isFeatured: truehighlights the plan as "Most Popular" on the pricing grid.- One-time vs subscription: SecureStartKit defaults to one-time billing (
monthly === yearly === one-time price). To switch to subscription mode, changemode: 'payment'tomode: 'subscription'inactions/billing.tsand create recurring prices in Stripe. See Payments for the full switch.
Appearance
appearance: {
defaultTheme: 'system', // 'light' | 'dark' | 'system'
allowThemeToggle: true, // Show the toggle in the header
primaryColor: '#6366f1', // The brand color
}
primaryColor feeds the Tailwind primary token. Change it and every CTA, link, and accent color across the site updates.
Auth providers
auth: {
providers: ['email', 'google'],
}
Enabling a provider here is the first step. You also need to configure it in the Supabase dashboard (Authentication > Providers) with your OAuth client credentials. The full walkthrough for adding a new provider is in Recipes: Add an OAuth provider.
Admin panel
admin: {
enabled: true,
superAdminEmails: ['you@yourdomain.com'],
}
Only users whose email exactly matches an entry in superAdminEmails can access /admin. The check is enforced server-side in the admin layout, not client-side. The list is in config.ts (not a database table) because admin status is an architectural decision, not a per-user setting.
SEO
seo: {
defaultTitle: 'YourSaaS, Build faster with security built-in',
titleTemplate: '%s | YourSaaS',
description: 'A production-ready Next.js SaaS template.',
keywords: ['saas', 'template', 'nextjs'],
ogImage: '/og.png',
twitterHandle: '@yoursaas',
}
These feed the default <head> metadata. Per-page metadata in App Router generateMetadata() overrides these defaults.
Changelog
changelog: {
enabled: true,
}
When enabled, a /changelog page renders MDX files from content/changelog/. Each entry uses standard frontmatter (title, date, version, categories). Set enabled: false to hide the changelog route entirely.