Skip to content

Configuration ​

What you'll learn

Every option of easy-cms.config.ts: the top-level settings, collections, globals, branding and plugins.

Before this page: Getting started.

Everything about your content lives in easy-cms.config.ts at the project root:

ts
import { defineConfig, isAdmin } from '@easy-cms/core'
import { sqlite } from '@easy-cms/db-sqlite'

export default defineConfig({
  secret: process.env.EASY_CMS_SECRET ?? '',
  db: sqlite({ url: 'file:./cms.db' }),
  admin: { locale: 'th' },
  collections: [
    {
      slug: 'posts',
      drafts: true,
      useAsTitle: 'title',
      access: { read: () => true, update: isAdmin },
      fields: [
        { name: 'title', type: 'text', required: true },
        { name: 'body', type: 'richText' },
      ],
    },
  ],
  globals: [{ slug: 'site', fields: [{ name: 'siteName', type: 'text' }] }],
})

defineConfig returns the config unchanged, keeping its literal types so documents can be typed from it. The config is validated at startup; every problem is reported at once with where it is and how to fix it.

Top-level options ​

OptionDefault
secret—Required, at least 32 characters. Signs sessions. Read it from an env var.
db—Required. A database adapter: sqlite() or postgres(). See Databases.
serverURL—Public origin such as https://example.com. Makes media URLs absolute.
webhooks[]Endpoints notified when content changes. See Webhooks.
cronSecretCRON_SECRETLets a cron run scheduled jobs at <api>/jobs/run.
localization—{ locales, defaultLocale?, fallback? }: content in several languages. See Localization.
cors[]Origins whose browser code may call the REST API, or '*' for any (anonymous requests). Origins in auth.trustedOrigins are always allowed, with cookies.
routes.api/api/cmsWhere the REST API is served.
admin.path/adminWhere the admin UI is served.
admin.localeenDefault admin language: en or th.
admin.siteUrl/ (Nuxt, Next.js)The public site, for the admin's "View site" button: a path or an https:// URL.
admin.menuconfig orderOrder of collections in the admin menu by slug, e.g. ['posts', 'categories', 'media']; others follow, the media library last. User accounts are under Settings.
admin.brand—{ name, logo, color }: your or your client's brand in the admin. See Branding the admin.
admin.modules[]JavaScript modules with Web Components for the admin, by package export or path; usually added by plugins.
authSee Users & auth.
uploadSee Uploads & media.
collections[]See below.
globals[]See below.
endpoints[]Custom REST endpoints: { path, method, handler }. See Plugins.
plugins[]Functions (config) => config, run in order before validation. See Plugins.

Collections ​

A collection is a type of content with many documents: posts, products, pages.

Option
slugURL and table name: lowercase letters, digits, -, _.
fieldsThe fields.
labels{ singular, plural }, each a string or { en, th }.
useAsTitleTop-level field shown as the document title in the admin.
editIn'drawer': create and edit in a panel over the list, for small collections such as categories; relationship fields to it get a "Create" button that opens the same panel. Collections with drafts, versions or preview always use the full page.
admin{ group: 'settings' } lists the collection under Settings in the menu (with Users and API keys) instead of with the content; { sidebar } adds admin components; { list: { tree: 'parent', sort: 'title' } } shows the list as a tree along a relationship to the same collection, and sets its default order.
iconIcon in the admin menu (default file-text); one of the names under Branding the admin.
draftsAdds status (draft | published). See Drafts.
versionstrue or { max }: keep a version of every save, with history and restore; with drafts, drafts of published documents are kept separately. See Versions.
preview({ doc }) => url: the page that shows a document, for live preview.
admin.sidebarPanels from admin components in the edit page's side column.
schedulePublish and unpublish at a set time (needs drafts). See Scheduled publishing.
access{ read, create, update, delete }. See Access control.
hooksSee Hooks.

Every document also has id (integer), createdAt and updatedAt.

Two collections are built in: users and media. Declare a collection with the same slug to add fields, access rules or hooks to them.

Reserved slugs: admin, globals, jobs, sessions, login-attempts, document-versions, scheduled-jobs, migrations, access.

Globals ​

A global has exactly one document: site settings, navigation, a footer.

ts
globals: [
  {
    slug: 'site',
    label: { en: 'Site settings', th: 'ตั้งค่าเว็บไซต์' },
    access: { read: () => true },
    fields: [
      { name: 'siteName', type: 'text', defaultValue: 'My site' },
      { name: 'menu', type: 'array', fields: [{ name: 'label', type: 'text' }, { name: 'url', type: 'text' }] },
    ],
  },
],

Globals accept fields, label, icon, drafts, versions, preview, admin, access (read, update) and hooks (beforeChange, afterChange, afterRead).

Branding the admin ​

Agencies can show their client's brand instead of Easy CMS's:

ts
admin: {
  brand: {
    name: 'Acme Coffee',     // menu, login page and browser tab
    logo: '/acme-logo.svg',  // a path on your site or an https:// URL
    color: '#b45309',        // main color; lighter and darker shades are derived
  },
},
collections: [
  { slug: 'posts', icon: 'newspaper', fields: [/* … */] },
  { slug: 'menu', icon: 'utensils', fields: [/* … */] },
],
globals: [{ slug: 'site', icon: 'house', fields: [/* … */] }],

Text on the brand color turns dark when white would be hard to read. Each user picks light, dark or their system's theme in the menu.

Icons (Lucide): file-text, newspaper, book-open, notebook, folder, tag, tags, image, images, video, music, file, users, user, building, store, shopping-bag, shopping-cart, package, box, calendar, calendar-days, map-pin, globe, house, layout-grid, layers, star, heart, message-square, mail, phone, briefcase, graduation-cap, utensils, car, settings, sliders-horizontal, palette, megaphone, bell, link, quote, circle-help, award, ticket, camera.

Plugins ​

A plugin receives the config and returns a new one, so it can add fields, collections, endpoints and admin components:

ts
import { seoPlugin } from '@easy-cms/plugin-seo'

export default defineConfig({ /* … */ plugins: [seoPlugin({ collections: ['posts'] })] })

See Plugins for the official plugins and how to write your own.

Next steps ​

Released under the MIT License.