Roots
import {Config} from 'alinea'
import {Home, Settings} from './schema'
export const pages = Config.root('Pages', {
contains: ['Page', 'Blog'],
i18n: {locales: ['en', 'fr']},
children: {
index: Config.page({type: Home, fields: {title: 'Home'}})
}
})
export const settings = Config.root('Settings', {
contains: [],
children: {
settings: Config.page({type: Settings, fields: {title: 'Site settings'}})
}
})Options
Config.root(label, options) takes the label shown in the sidebar and:
contains: the types that can be created at the top level of the root. Entries below them follow thecontainsof their parent's type.children: entries that always exist in this root, see "Seeded entries" below.i18n: make the root translatable with{locales: ['en', 'fr']}. The first locale is the default in the dashboard.overview: how the dashboard lists the top-level entries: columns, the default order (sort), the layout and actions, see below.icon: a React component shown next to the root in the sidebar.preview: turn live previews on or off for entries in this root, or pass a component that renders the preview. A type's ownpreviewtakes precedence.view: a React component, or a path to one, that replaces the dashboard view of the root. It receives{root}. Use it to add a custom page to the dashboard.openByDefault: open this root when the workspace is opened without a specific root. Otherwise the first root opens.orderChildrenBy(deprecated): sort the top-level entries by one or more fields. Useoverview.sort.
The key of a root (pages) is its name in content files and queries. It must start with a letter and contain only letters, digits and underscores. The first root of a workspace is the one the dashboard opens by default, unless another root sets openByDefault.
Overview
Opening a root lists its top-level entries. overview adds columns and sets the default order, which the sidebar tree follows too:
import {Config, Field} from 'alinea'
export const Author = Config.document('Author', {
fields: {
avatar: Field.image('Avatar'),
role: Field.text('Role')
}
})
export const authors = Config.root('Authors', {
contains: ['Author'],
overview: {
columns: {
role: Config.column({header: 'Role', select: Author.role})
},
sort: {asc: Author.title},
layout: 'cards'
}
})See Overviews for all options. Types configure the list of their children the same way.
Seeded entries
children creates entries from your config. Alinea adds them when it finds them missing, in every locale of the root, and editors can't move or delete them. That's the way to make sure a home page, a settings entry or a fixed overview page always exists:
import {Config} from 'alinea'
import {Blog, Home} from './schema'
export const pages = Config.root('Pages', {
contains: ['Page'],
children: {
// The key is the path: "index" becomes the home page at /
index: Config.page({type: Home, fields: {title: 'Home'}}),
blog: Config.page({type: Blog, fields: {title: 'Blog'}})
}
})Config.page takes:
type(required): the type of the entry. It must be in your schema.fields: default field values. They apply until an editor saves the entry. Without atitle, the key is used.children: seeded entries below this one, in the same form.
Removing a page from children doesn't delete its entry: it stays in your content and becomes a regular entry that editors can move and delete.
To query a seeded settings entry, filter by its type: cms.get({type: Settings}). If you created the entry by hand before seeding it, Alinea adopts the existing file with the same path.
Translations
With i18n, editors can translate every entry of the root into each locale, and each translation is a separate version with its own path and content. Urls start with the locale (/en/about, /fr/about), and content files are stored in a folder per locale (content/pages/en/about.json). Query a translation with the locale option, or all of them with Query.translations.
Leave i18n out of roots that aren't translated, such as a list of authors. See Internationalization for translating pages, per-field translations and dropping the locale from urls.
import {Config} from 'alinea'
export const pages = Config.root('Pages', {
contains: ['Page'],
i18n: {locales: ['en', 'fr', 'nl']}
})Roots in queries
Roots are available on the CMS instance under their workspace, cms.workspaces.main.pages, and can be passed to the root or location query options:
import {cms} from '@/cms'
import {Query} from 'alinea'
const navigation = await cms.find({
root: cms.workspaces.main.pages,
locale: 'en',
level: 0,
select: {title: Query.title, url: Query.url}
})