Configuration Guide
Configuration is split between public env values, server-only secrets, app settings, branding, navigation, pricing, email, SEO, and rate-limit policy.
On this page
Configuration source map
App identity and public env
Central config normalizes site URL, brand name, support email, and production URL safety.
src/lib/config.tssrc/config/app-identity.ts
Database-backed settings
Website, SEO, billing, waitlist, and localization settings are validated before writes and normalized before reads.
src/features/settings/server/schemas/settings.tssrc/features/settings/server/queries/settings.tssrc/features/settings/server/actions/website-settings.ts
Navigation and access
Dashboard navigation is tied to RBAC feature gates so visible links and route access share the same source of truth.
src/lib/auth/rbac/nav-config.tssrc/lib/auth/rbac/server.tssrc/lib/auth/rbac/features.ts
Pricing, email, SEO, and limits
Provider pricing, email delivery config, metadata builders, and route limits are each owned near the runtime boundary that uses them.
src/features/billing/server/catalog/configuration.tssrc/features/notifications/server/delivery/transport/resend/sender-config.tssrc/lib/seo/metadata/builders.tssrc/lib/security/rate-limit/policy.ts
Production URL guard
Source: src/lib/config.ts
Production deployments must use HTTPS and cannot point the canonical public URL at localhost.
function assertProductionUrl(name: string, value: string) {
const parsed = new URL(value);
if (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1") {
throw new Error(`${name} must not use localhost in production.`);
}
if (parsed.protocol !== "https:") {
throw new Error(`${name} must use HTTPS in production.`);
}
}Rate-limit policy resolver
Source: src/lib/security/rate-limit/policy.ts
Limits have safe defaults and optional env overrides at the policy boundary.
export function getRateLimitPolicy(name: RateLimitPolicyName): RateLimitPolicy {
const base = DEFAULT_POLICIES[name];
const envPrefix = `RATE_LIMIT_${name.toUpperCase()}`;
const limit = readNumberEnv(`${envPrefix}_LIMIT`, base.limit);
const windowSeconds = readNumberEnv(`${envPrefix}_WINDOW_SECONDS`, base.windowSeconds);
return { ...base, limit, windowSeconds };
}