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:
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
| Option | Default | |
|---|---|---|
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. |
cronSecret | CRON_SECRET | Lets 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/cms | Where the REST API is served. |
admin.path | /admin | Where the admin UI is served. |
admin.locale | en | Default 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.menu | config order | Order 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. |
auth | See Users & auth. | |
upload | See 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 | |
|---|---|
slug | URL and table name: lowercase letters, digits, -, _. |
fields | The fields. |
labels | { singular, plural }, each a string or { en, th }. |
useAsTitle | Top-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. |
icon | Icon in the admin menu (default file-text); one of the names under Branding the admin. |
drafts | Adds status (draft | published). See Drafts. |
versions | true 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.sidebar | Panels from admin components in the edit page's side column. |
schedule | Publish and unpublish at a set time (needs drafts). See Scheduled publishing. |
access | { read, create, update, delete }. See Access control. |
hooks | See 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.
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:
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:
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
- Fields: the fields of your collections.
- Access control: who may read and change what.