nextjs-cms

Configuration

How cms.config.ts works, and the options most projects change first.

All project-wide settings live in cms.config.ts at the project root. Every option has a default, so an empty config works:

cms.config.ts
import { defineConfig } from 'nextjs-cms/core/config'

export default defineConfig({})

defineConfig is an identity helper that gives you autocompletion and type checking. For example, localization.defaultLocale only accepts codes you listed in localization.locales.

Good to know:

The CMS looks for cms.config.{ts,mts,cts,js,mjs,cjs,json} in the project root. It is validated with Zod when loaded, so an invalid value stops the app with an error. Unknown top-level keys are silently ignored, which is one more reason to use defineConfig: TypeScript catches the typo. In development, config changes are picked up without a restart.

Branding

cms.config.ts
export default defineConfig({
    ui: {
        title: 'Acme CMS', // browser tab title
        logo: '/logo.svg', // file in /public
        logoText: { text: 'Acme', position: 'right' }, // 'left' | 'right' | 'top' | 'bottom'
        defaultTheme: 'light', // 'light' | 'dark' (default 'dark')
    },
})

What the sidebar header shows:

You setSidebar shows
logo and logoTextLogo, with the text on the chosen side
logo onlyLogo, scaled to the header height
logoText onlyThe text, centered (position is ignored)
neithertitle, centered

Sections folder

cms.config.ts
import { resolve } from 'node:path'

export default defineConfig({
    sections: {
        path: resolve(process.cwd(), 'sections'), // default: 'sections'
        strict: false,
        category: { allowRecursiveDelete: false },
    },
})
  • strict: when true, one broken section file makes the CMS load no sections. Useful in CI to fail loudly. When false (default), broken sections are skipped and reported, and the rest keep working.
  • category.allowRecursiveDelete: global switch for deleting a category together with its children. A category section must also opt in. See Category Section.

Uploads and images

cms.config.ts
export default defineConfig({
    media: {
        upload: {
            path: '.uploads', // where files are written, relative to the project root
            preserveExtension: true,
        },
        images: {
            background: { r: 255, g: 255, b: 255, alpha: 1 }, // padding for fit: 'contain'
            image: {
                size: { width: 1200, height: 630, fit: 'cover' },
                quality: 85, // 50-100
            },
            thumbnail: {
                size: { width: 400, height: 300, fit: 'cover' },
                quality: 80,
            },
            watermark: false, // or { imagePath: './watermark.png', position: 'bottom-right', ... }
        },
    },
})

These are defaults. Every photoField can override its size, thumbnail, and watermark. Read Media & Uploads for how files are stored and served.

Admin UI languages

The admin interface ships in English. To offer more languages, import dictionaries and list them:

cms.config.ts
import en from 'nextjs-cms/translations/base/en'
import ar from '@nextjscms/translations/ar'

export default defineConfig({
    i18n: {
        supportedLanguages: { en, ar },
        fallbackLanguage: 'en',
    },
})

Each admin picks their language in the admin's settings.

Content localization

Different from UI languages: this lets editors translate content (a post's title in English and Arabic).

cms.config.ts
export default defineConfig({
    localization: {
        locales: [
            { code: 'en', label: 'English', flag: '/img/flags/en.svg' },
            { code: 'ar', label: 'العربية', rtl: true, flag: '/img/flags/ar.svg' },
        ],
        defaultLocale: 'en',
    },
})

Then mark fields with localized: true. The full story is in the Localization guide.

Plugins

cms.config.ts
import { googleAnalyticsPlugin } from '@nextjscms/plugin-google-analytics'

export default defineConfig({
    plugins: [googleAnalyticsPlugin],
})

See Using Plugins.

Everything else

The full list of options, types and defaults is in the cms.config.ts reference.