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'
}
FieldTypeRequiredDescription
namestringYesDisplay name shown in the admin panel
urlstringYesFull public URL of your CMS (used for CORS, sitemap)
adminPathstringNoPath to serve the admin UI. Set to false to disable
apiPathstringNoBase 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',
}
FieldTypeDefaultDescription
urlstringPostgreSQL connection string
pool.minnumber2Minimum pool connections
pool.maxnumber10Maximum pool connections
pool.idleTimeoutMsnumber30000Idle connection timeout in ms
pool.connectionTimeoutMsnumber5000Time to wait for a connection from the pool
debugbooleanfalseLog 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' } },
}
FieldTypeDefaultDescription
portnumber3001TCP port to listen on
hoststring0.0.0.0Bind address
trustProxybooleanfalseTrust X-Forwarded-* headers from reverse proxies
bodyLimitnumber10485760Max request body size in bytes
loggerPino logger configPassed 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,
}
FieldTypeDefaultDescription
localesstring[]['en']All supported locale codes
defaultLocalestring'en'Fallback locale if content has no translation
fallbacksobject{}Locale fallback chains
routingbooleanfalsePrefix 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 } } },
    },
  },
})