Content › Configuration
Introduction
Content
Using content
Plugins
Operations
Recipes
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, and is where password links point (needed for them in production). |
webhooks | [] | Endpoints notified when content changes. See Webhooks. |
cronSecret | CRON_SECRET | Lets a cron run scheduled jobs at <api>/jobs/run. At least 32 characters. |
jobs | [] | Your own background work, every few seconds or at a time of day. See Jobs. |
timeZone | the server's | IANA zone of times of day in the config (jobs[].at, backups.at), e.g. Asia/Bangkok. |
localization | — | { locales, defaultLocale?, fallback? }: content in several languages (leave it out, or false, for one). 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.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. |
admin.icon | Icon in the admin menu (default file-text); one of the names under Branding the admin. |
admin.order | Its place in its menu group, e.g. 1: lower first; collections without one come after, in config order. The media library comes last, user accounts are under Settings. |
admin.group | 'settings' lists the collection under Settings in the menu (with Users and API keys) instead of with the content; false leaves it out of the menu (links still reach it). See The menu. |
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.list | { tree: 'parent', sort: 'title' } shows the list as a tree along a relationship to the same collection, and sets its default order. |
drafts | Adds status (draft | published). See Drafts. |
versions | true or { keep }: 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, auth.
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, drafts, versions, preview, admin (icon, order,
group, sidebar, layout), access (read, update) and hooks (beforeValidate,
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', admin: { icon: 'newspaper' }, fields: [/* … */] },
{ slug: 'menu', admin: { icon: 'utensils' }, fields: [/* … */] },
],
globals: [{ slug: 'site', admin: { 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, key, chart-column, chart-line.
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.