Configuration
The flamecms.config.ts file is the single source of truth for your FlameCMS instance. It is loaded at startup and type-checked by TypeScript, so typos and invalid values are caught before the server starts.
defineConfig()
All configuration is wrapped in defineConfig(), which provides full TypeScript intellisense:
import { defineConfig } from 'flamecms'
export default defineConfig({
// ... options
})
The function returns the config object unchanged — it exists solely to provide TypeScript type inference and IDE autocomplete.
site
Top-level metadata about your CMS instance.
site: {
name: 'My CMS',
url: 'https://cms.example.com',
adminPath: '/admin', // default: '/admin'
apiPath: '/api', // default: '/api'
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name shown in the admin panel |
url | string | Yes | Full public URL of your CMS (used for CORS, sitemap) |
adminPath | string | No | Path to serve the admin UI. Set to false to disable |
apiPath | string | No | Base path for the REST API |
database
PostgreSQL connection options.
database: {
url: process.env.DATABASE_URL!,
// Optional pool settings
pool: {
min: 2,
max: 10,
idleTimeoutMs: 30_000,
connectionTimeoutMs: 5_000,
},
// Optional: log all SQL queries (verbose, use only in development)
debug: process.env.NODE_ENV === 'development',
}
| Field | Type | Default | Description |
|---|---|---|---|
url | string | — | PostgreSQL connection string |
pool.min | number | 2 | Minimum pool connections |
pool.max | number | 10 | Maximum pool connections |
pool.idleTimeoutMs | number | 30000 | Idle connection timeout in ms |
pool.connectionTimeoutMs | number | 5000 | Time to wait for a connection from the pool |
debug | boolean | false | Log all SQL queries to stdout |
server
HTTP server configuration (Fastify).
server: {
port: 3001,
host: '0.0.0.0',
// Trust X-Forwarded-For when behind Nginx/proxy
trustProxy: true,
// Request body size limit
bodyLimit: 10 * 1024 * 1024, // 10 MB
// Custom Fastify logger
logger: process.env.NODE_ENV === 'production'
? { level: 'info' }
: { level: 'debug', transport: { target: 'pino-pretty' } },
}
| Field | Type | Default | Description |
|---|---|---|---|
port | number | 3001 | TCP port to listen on |
host | string | 0.0.0.0 | Bind address |
trustProxy | boolean | false | Trust X-Forwarded-* headers from reverse proxies |
bodyLimit | number | 10485760 | Max request body size in bytes |
logger | Pino logger config | — | Passed directly to Fastify — full Pino options apply |
plugins
An array of plugin imports. Order matters — plugins are initialised in sequence.
import flameSEO from '@flamecms/seo-sitemap'
import flameCache from '@flamecms/cache-redis'
import flameOAuth from '@flamecms/auth-oauth'
import flameMedia from '@flamecms/media-s3'
plugins: [
flameSEO(),
flameCache({
url: process.env.REDIS_URL!,
ttl: 60, // seconds
excludeRoutes: ['/api/auth'],
}),
flameOAuth({
providers: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
}),
flameMedia({
bucket: process.env.S3_BUCKET!,
region: process.env.AWS_REGION!,
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
}),
]
i18n
Multi-language configuration.
i18n: {
locales: ['en', 'zh-TW', 'ja'],
defaultLocale: 'en',
// Fallback chain per locale
fallbacks: {
'zh-TW': ['zh', 'en'],
'ja': ['en'],
},
// Generate locale-prefixed URLs (/en/posts, /zh-TW/posts)
routing: true,
}
| Field | Type | Default | Description |
|---|---|---|---|
locales | string[] | ['en'] | All supported locale codes |
defaultLocale | string | 'en' | Fallback locale if content has no translation |
fallbacks | object | {} | Locale fallback chains |
routing | boolean | false | Prefix API routes with locale code |
permissions
Define roles and their access rights.
permissions: {
roles: {
admin: {
collections: { '*': { read: true, create: true, update: true, delete: true } },
},
editor: {
collections: {
posts: {
read: ['*'],
create: ['title', 'body', 'tags', 'excerpt'],
update: ['title', 'body', 'tags', 'excerpt'],
delete: false,
},
media: {
read: true, create: true, update: false, delete: false,
},
},
},
author: {
collections: {
posts: {
read: { filter: { author: '{{user.id}}' } },
create: ['title', 'body', 'excerpt'],
update: { filter: { author: '{{user.id}}' }, fields: ['title', 'body', 'excerpt'] },
delete: false,
},
},
},
},
}
Complete Configuration Example
// flamecms.config.ts
import { defineConfig } from 'flamecms'
import flameSEO from '@flamecms/seo-sitemap'
import flameCache from '@flamecms/cache-redis'
export default defineConfig({
site: {
name: 'Acme CMS',
url: process.env.SITE_URL || 'http://localhost:3001',
adminPath: '/admin',
apiPath: '/api',
},
database: {
url: process.env.DATABASE_URL!,
pool: { min: 2, max: 20 },
debug: process.env.NODE_ENV !== 'production',
},
server: {
port: Number(process.env.PORT) || 3001,
host: '0.0.0.0',
trustProxy: true,
bodyLimit: 20 * 1024 * 1024,
},
i18n: {
locales: ['en', 'zh-TW'],
defaultLocale: 'en',
fallbacks: { 'zh-TW': ['en'] },
},
plugins: [
flameSEO({ sitemapPath: '/sitemap.xml' }),
flameCache({ url: process.env.REDIS_URL!, ttl: 120 }),
],
permissions: {
roles: {
admin: { collections: { '*': { read: true, create: true, update: true, delete: true } } },
editor: { collections: { posts: { read: ['*'], create: ['title','body'], update: ['title','body'], delete: false } } },
},
},
})