Entry Collections
An entry collection contains multiple entries of the same type. Editors can usually create, edit, and delete entries within the collection. Typical use cases for entry collections include blog posts, tags, products or events. Each entry in the collection is represented by a separate file.
Note for Netlify/Decap CMS users
In Sveltia CMS, what was previously referred to as a folder collection in Netlify/Decap CMS is now called an entry collection. This change was made to better reflect the purpose and functionality of these collections within the CMS.
Creating an Entry Collection
Here is an example configuration defining a simple blog posts collection:
collections:
- name: blog
label: Blog Posts
label_singular: Blog Post
folder: content/blog
fields:
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "blog"
label = "Blog Posts"
label_singular = "Blog Post"
folder = "content/blog"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "blog",
"label": "Blog Posts",
"label_singular": "Blog Post",
"folder": "content/blog",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "blog",
label: "Blog Posts",
label_singular: "Blog Post",
folder: "content/blog",
fields: [
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}Options
The following options are commonly used when defining an entry collection:
name: (required) A unique identifier for the collection. Should not contain spaces or special characters.label: A human-readable name for the collection. If omitted, thenamevalue is used.label_singular: A human-readable singular name for the collection. If omitted, thelabelvalue is used. Used in some parts of the UI like the “Create new” button.description: A brief description of the collection, displayed in the UI. Basic Markdown formatting is supported, including bold, italic, strikethrough, code, and links.folder: (required) The folder path where the entries are stored, relative to the repository’s root directory. It can be an empty string (or.or/) to store entries in the root folder.fields: (required) An array defining the fields for each entry in the collection. Each field has aname,label, and optionalwidgettype.
File Format and Extension
Sveltia CMS supports various file formats for entry collections, including Markdown, YAML, JSON, and TOML. The default format is Markdown with YAML front matter.
The example below defines a simple blog posts collection:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
fields:
- { name: title, label: Title }
- { name: date, label: Date, widget: datetime }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "date"
label = "Date"
widget = "datetime"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "date", "label": "Date", "widget": "datetime" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
fields: [
{ name: "title", label: "Title" },
{ name: "date", label: "Date", widget: "datetime" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}By default, entry collections use the title field as the slug (filename). The default format is yaml-frontmatter with the md extension, meaning each entry will be saved as a Markdown file with YAML front matter. A Markdown field named body is treated as the main content of the file, while other fields are stored in the front matter.
If you create a blog post with the title “My First Post”, the file will be saved at content/posts/my-first-post.md, with the following content:
---
title: My First Post
date: 2024-06-01T12:00:00Z
---
This is the body of my first post.You can customize the file format using the format property of the collection. The example below shows how to use JSON for file format:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
format: json[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "json"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"format": "json"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
format: "json",
},
],
}The output file for a post created with this configuration would look like this:
{
"title": "My First Post",
"date": "2024-06-01T12:00:00Z",
"body": "This is the body of my first post."
}Format
The following file formats are supported for entry collections. You can specify the desired format using the format option to define how entries are parsed and saved. The default format is yaml-frontmatter.
ymloryaml: YAML files with theymlextension by default.toml: TOML files with thetomlextension by default.json: JSON files with thejsonextension by default.yaml-frontmatter: Markdown files with YAML front matter, themdextension and the---delimiter by default.toml-frontmatter: Markdown files with TOML front matter, themdextension and the+++delimiter by default.json-frontmatter: Markdown files with JSON front matter, themdextension and the{/}delimiter by default.frontmatter: Markdown files with front matter in any of the supported formats. The format is automatically detected based on the front matter delimiters. However, when creating new entries, the format defaults toyaml-frontmatter. Themdextension and---delimiter are used by default.raw: Raw text files with thetxtextension by default. When using this format, make sure to have only one field namedbodywith thewidgettype set tocode,markdown,richtextortext. This is useful for a file collection that manages plain text files without any front matter, such as JSON, XML, or CSV files.
The JSON and YAML formats can be customized via the global output option.
Deprecation Notice
The collection-level yaml_quote option has been deprecated in favor of the quote option in the global output option. The yaml_quote option will be removed in Sveltia CMS v1.0.0. If you are upgrading from an older version, update your configuration accordingly. yaml_quote: true is equivalent to quote: double in the global YAML format options.
If you want to use a different file format, register a custom format using the Custom File Formats API and specify its name in the format option.
Extension
You can customize the file extension using the extension property of the collection. The default extensions for each format are explained above, but you can change them as needed. For example, to use the markdown extension for Markdown files with YAML front matter:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
extension: markdown[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
extension = "markdown"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"extension": "markdown"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
extension: "markdown",
},
],
}You can use any valid file extension, such as html, txt, or mdx. Just make sure that the file format and extension are compatible. If there is an obvious mismatch, Sveltia CMS will raise a validation error. For example, if you use json format with md extension, it will result in an error because JSON files should have a json extension.
Front Matter Delimiter
The front matter delimiter can be customized using the frontmatter_delimiter option. It accepts either a string or an array of two strings representing the opening and closing delimiters. For example, to use ~~~ as the delimiter for TOML front matter:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
format: toml-frontmatter
frontmatter_delimiter: ~~~ # or [~~~, ~~~][[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "toml-frontmatter"
frontmatter_delimiter = "~~~"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"format": "toml-frontmatter",
"frontmatter_delimiter": "~~~"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
format: "toml-frontmatter",
frontmatter_delimiter: "~~~",
},
],
}Managing Entry Slugs
Sveltia CMS provides several ways to customize the slug (filename) of an entry in a collection.
Global Slug Options
The slug option defined at the top-level of the configuration file applies to all collections. The default settings are as follows:
slug:
encoding: unicode
clean_accents: false
sanitize_replacement: '-'[slug]
encoding = "unicode"
clean_accents = false
sanitize_replacement = "-"{
"slug": {
"encoding": "unicode",
"clean_accents": false,
"sanitize_replacement": "-"
}
}{
slug: {
encoding: "unicode",
clean_accents: false,
sanitize_replacement: "-"
},
}The available options are:
encoding: Specifies the encoding method for slugs. Supported values areunicode(default) andascii.unicode: Allows Unicode characters in slugs, preserving non-Latin scripts.ascii: Sanitizes slugs to ASCII characters only. The allowed characters are 0-9, a-z, A-Z, hyphen (-) underscore (_) and tilde (~). Other characters are replaced with the value specified in thesanitize_replacementoption.
clean_accents: A boolean value indicating whether to remove accents from characters in slugs. If enabled, accented characters are converted to their unaccented equivalents (e.g.,ébecomese). Also, certain characters like German umlauts are transliterated to their ASCII equivalents (e.g.,ßbecomesss). The default value isfalse.sanitize_replacement: A string used to substitute invalid characters. The default value is a hyphen (-).maxlength: An integer specifying the maximum length of the slug. If the generated slug exceeds this length, it will be truncated. This is useful for CI/CD services or filesystems that impose filename length restrictions. The default value isundefined, meaning there is no length limit.trim: A boolean value indicating whether to trim leading and trailingsanitize_replacementcharacters from the slug. The default value istrue.lowercase: A boolean value indicating whether to convert the slug to lowercase. The default value istrue. Changing this tofalsewill preserve the original casing of the title or identifier field.
Deprecation Notice
The collection-level slug_length option has been deprecated in favor of the maxlength global slug option described above. The slug_length option will be removed in Sveltia CMS v1.0.0. If you are upgrading from an older version, update your configuration accordingly.
How Slugs are Generated
By default, Sveltia CMS uses the title field as the slug (filename) for entries in a collection.
If a collection only has the Markdown body field, an entry slug will be generated from a header in the body, if exists. This aims to support a typical VitePress or Docusaurus setup. If no title or header is found, a part of a random UUID will be used to ensure uniqueness.
Defining Entry Slugs
The slug option allows you to define a custom template for generating entry slugs using various template tags and field names.
For example, to create slugs that include the year and month of creation along with the entry slug, you can use the following configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
slug: '{{year}}-{{month}}-{{slug}}'[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
slug = "{{year}}-{{month}}-{{slug}}"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"slug": "{{year}}-{{month}}-{{slug}}"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
slug: "{{year}}-{{month}}-{{slug}}",
},
],
}Any field name defined in the collection’s fields option can be used as a template tag in the slug option. For example, if you have a date field in the collection, you can use {{date}} in the slug option to include the date in the slug. For nested fields, use dot notation, e.g. {{author.name}}.
To use a field named slug, you need to prefix it with fields., like {{fields.slug}}, to avoid confusion with the slug template tag itself.
You can use string transformations with these template tags as well. For example, to create slugs that include the full date in YYYY-MM-DD format along with a custom slug field, you can use the following configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
slug: "{{date | date('YYYY-MM-DD')}}-{{fields.slug}}"[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
slug = "{{date | date('YYYY-MM-DD')}}-{{fields.slug}}"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"slug": "{{date | date('YYYY-MM-DD')}}-{{fields.slug}}"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
slug: "{{date | date('YYYY-MM-DD')}}-{{fields.slug}}",
},
],
}TIP
The slug option value should not contain slashes (/). If you need to create a nested folder structure for entries, use the path option instead.
Slug Template Tags
The following template tags are supported in the slug option:
{{slug}}: The slugified version of the entry’stitlefield (or the field defined with theidentifier_fieldoption).{{year}}: 4-digit year of the entry creation date.{{month}}: 2-digit month of the entry creation date.{{day}}: 2-digit day of the entry creation date.{{hour}}: 2-digit hour of the entry creation date.{{minute}}: 2-digit minute of the entry creation date.{{second}}: 2-digit second of the entry creation date.
Additionally, the following unique identifier tags are available. These tags generate random values for each entry, ensuring uniqueness. This is particularly useful when the entry title may change later or when the title contains characters that are not suitable for filenames, such as non-Latin scripts.
{{uuid}}: A random UUID v4, e.g.4fc0917c-8aea-4ad5-a476-392bdcf3b642{{uuid_short}}: The last 12 characters of a random UUID v4, e.g.392bdcf3b642.{{uuid_shorter}}: The first 8 characters of a random UUID v4, e.g.4fc0917c.
Making Slugs Editable
By default, entry slugs are automatically generated based on the title field or the template defined in the slug option. However, you can allow users to edit the slug directly in the entry editor by including a special slug field in the slug option.
To make the slug editable, set the slug option to {{fields._slug}}. This will display a special slug editor UI that looks like a standard string field, but the value will be used as the entry slug.
Once the entry is created, the _slug field will be populated with the generated slug. Users can then modify it as needed using the slug editor, which can be accessed via the 3-dot menu in the entry editor.
To make the slug editable for each locale in an i18n-enabled collection, use set the slug option to {{fields._slug | localize}}.
Managing File Paths
Sveltia CMS provides a couple of options to customize the file paths of entries in a collection.
Using Subfolders
By default, Sveltia CMS saves entries directly under the specified folder using the slug as the filename. However, you can organize entries into subfolders using the path option.
Just like the slug option described above, the path option can use template tags to create dynamic folder structures. The slug template tags and string transformations can be used in the path option, along with any field names defined in the collection’s fields option. For nested fields, use dot notation, e.g. {{author.name}}.
For example, to save blog posts in subfolders based on the year and month of creation, you can use the following configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
path: '{{year}}/{{month}}/{{slug}}'[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
path = "{{year}}/{{month}}/{{slug}}"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"path": "{{year}}/{{month}}/{{slug}}"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
path: "{{year}}/{{month}}/{{slug}}",
},
],
}With the above configuration, a blog post created on June 15, 2025, with the title “My First Post” will be saved at content/posts/2025/06/my-first-post.md.
Creating Page Bundles
You can create nested structures like Hugo’s page bundles using the path, media_folder and public_folder options together. For example, to create a leaf bundle for each blog post, you can use the following configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
path: '{{slug}}/index'
media_folder: ''
public_folder: ''[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
path = "{{slug}}/index"
media_folder = ""
public_folder = ""{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"path": "{{slug}}/index",
"media_folder": "",
"public_folder": ""
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
path: "{{slug}}/index",
media_folder: "",
public_folder: "",
},
],
}With the above configuration, a blog post with the title “My First Post” will be saved at content/posts/my-first-post/index.md, and its media files will be stored in the same folder.
Constructing File Paths
A folder collection’s file path is determined by multiple factors: the i18n, folder, path, slug and extension options. The configuration can be complex, especially with i18n support, so let’s break it down.
- The
i18nglobal or collection option (optional)- It can be configured to add internationalization (i18n) support to your site.
- The
structureandomit_default_locale_from_file_pathoptions affect the entry file path.
- The
foldercollection option (required)- It specifies the folder where the collection entries are stored, relative to the repository’s root directory.
- It can contain slashes to create a nested folder structure.
- The
pathcollection option (optional)- It defaults to
{{slug}}, which is theslugcollection option value. - It can contain template tags.
- It can also contain slashes to create a nested folder structure.
- It defaults to
- The
slugcollection option (optional)- It defaults to
{{title}}, which is the entry’stitlefield value’s slugified version. - It can contain template tags but cannot contain slashes.
- It defaults to
- The
extensioncollection option (optional)- It defaults to
md.
- It defaults to
Looking at the above options, the entry file path can be constructed as follows:
- With i18n disabled:yaml
/<folder>/<path>.<extension> - With the
single_filei18n structureyaml/<folder>/<path>.<extension> - With the
multiple_filesi18n structure:yamlWhen the/<folder>/<path>.<locale>.<extension>omit_default_locale_from_file_pathi18n option is set totrue, the path depends on the locale:yaml/<folder>/<path>.<extension> # default locale /<folder>/<path>.<locale>.<extension> # other locales - With the
multiple_foldersi18n structure:yamlWhen the/<folder>/<locale>/<path>.<extension>omit_default_locale_from_file_pathi18n option is set totrue, the path depends on the locale:yaml/<folder>/<path>.<extension> # default locale /<locale>/<folder>/<path>.<extension> # other locales - With the
multiple_root_foldersi18n structure:yamlWhen the/<locale>/<folder>/<path>.<extension>omit_default_locale_from_file_pathi18n option is set totrue, the path depends on the locale:yaml/<folder>/<path>.<extension> # default locale /<locale>/<folder>/<path>.<extension> # other locales
Creating Editable Nested Structures
With the nested and meta options, you can organize contents that have a hierarchical relationship, such as categories and subcategories, and allow editors to create nested entries easily. This feature is called nested collections in Netlify/Decap CMS.
Unimplemented
This feature is not yet supported in Sveltia CMS. It will be added in the near future.
Managing Preview Paths
The preview_path option allows you to define a custom URL path for previewing entries on your live site. This option accepts a string with template tags that will be replaced with entry-specific values when generating the preview URL. The CMS provides links to preview the entries based on this URL structure.
The slug template tags can be used in the preview_path option, with the following exceptions:
{{slug}}: the entire slug of the entry, not just the slugified entry identifier.{{year}},{{month}},{{day}},{{hour}},{{minute}},{{second}}: these tags are based on the entry’s DateTime field. The CMS looks for the first DateTime field in the collection to extract the date and time information. Use thepreview_path_date_fieldoption to specify a different date field. If no DateTime field is found, thepreview_pathoption will be ignored.{{dirname}}: the directory name of the entry file relative to the collectionfolder. This is useful when using thepathoption to create subfolders.{{filename}}: the filename of the entry without the extension. This is useful when you want to use the exact filename in the preview URL.{{extension}}: the file extension of the entry. This is useful when you want to include the file type in the preview URL.{{locale}}: the locale code of the entry when using i18n support. This is useful when you want to include the locale in the preview URL.
You can use string transformations with these template tags.
The example below shows how to configure a blog posts collection with a custom preview URL structure.
collections:
- name: posts
label: Blog Posts
folder: /content/posts
preview_path: '/blog/{{year}}/{{month}}/{{slug}}'
preview_path_date_field: created_at
fields:
- { name: title, label: Title }
- { name: created_at, label: Created At, widget: datetime }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
preview_path = "/blog/{{year}}/{{month}}/{{slug}}"
preview_path_date_field = "created_at"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "created_at"
label = "Created At"
widget = "datetime"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"preview_path": "/blog/{{year}}/{{month}}/{{slug}}",
"preview_path_date_field": "created_at",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "created_at", "label": "Created At", "widget": "datetime" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
preview_path: "/blog/{{year}}/{{month}}/{{slug}}",
preview_path_date_field: "created_at",
fields: [
{ name: "title", label: "Title" },
{ name: "created_at", label: "Created At", widget: "datetime" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}With the above configuration, a blog post created on June 15, 2025, with the title “My First Post” will have a preview URL of /blog/2025/06/my-first-post.
Controlling Entry Creation
Sveltia CMS provides options to control entry creation and deletion, limit the number of entries, and hide collections from the Sveltia CMS interface.
Disabling Creation and Deletion
You can disable entry creation and deletion by setting the create option to false and the delete option to false in the collection definition. This is useful for collections where entries are managed programmatically or through other means, and you don’t want editors to create or delete entries.
collections:
- name: posts
label: Blog Posts
folder: /content/posts
create: false
delete: false
fields:
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
create = false
delete = false
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"create": false,
"delete": false,
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
create: false,
delete: false,
fields: [
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}Breaking change from Netlify/Decap CMS
In Sveltia CMS, the create option for entry collections defaults to true because, in 99.99% of cases, users want to create new entries and adding create: true to every collection is redundant. To disable entry creation, set create: false explicitly.
Limiting Entry Count
You can limit the number of entries in an entry collection using the limit option. This is useful for collections where you want to restrict the number of items, such as featured articles or top products.
collections:
- name: featured_articles
label: Featured Articles
folder: /content/featured_articles
limit: 5
fields:
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "featured_articles"
label = "Featured Articles"
folder = "/content/featured_articles"
limit = 5
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "featured_articles",
"label": "Featured Articles",
"folder": "/content/featured_articles",
"limit": 5,
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "featured_articles",
label: "Featured Articles",
folder: "/content/featured_articles",
limit: 5,
fields: [
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}With the above configuration, editors can only create up to 5 entries in the featured_articles collection. Once the limit is reached, the “Create new” button will be disabled in the Sveltia CMS interface.
Hiding the Collection
You can hide an entry collection from the Sveltia CMS interface using the hide option. This is useful for collections that are managed programmatically or through other means, and you don’t want editors to see or modify them.
collections:
- name: posts
label: Blog Posts
folder: /content/posts
hide: true
fields:
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
hide = true
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"hide": true,
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
hide: true,
fields: [
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}When the hide option is set to true, the collection will not appear in the Sveltia CMS interface, and editors will not be able to access or modify its entries.
Including and Excluding Entries
Sometimes, you may want to include or exclude specific entries from being displayed in the Sveltia CMS interface. Sveltia CMS provides options to manage this.
Managing Hugo’s Special Index file
By default, Hugo’s special _index.md file are hidden in a folder collection unless the path option is configured to end with _index and the extension is set to md. You have to create a file collection to manage the file, since it usually comes with a different set of fields than regular entry fields.
The index_file option allows you to include and manage the special index file within the same folder collection. This way, editors can easily access and edit the index file alongside regular entries.
collections:
- name: posts
label: Blog posts
folder: /content/posts
fields: # Fields for regular entries
- { name: title, label: Title }
- { name: date, label: Published Date, widget: datetime }
- { name: description, label: Description }
- { name: body, label: Body, widget: richtext }
index_file:
fields: # Fields for the index file
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog posts"
folder = "/content/posts"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "date"
label = "Published Date"
widget = "datetime"
[[collections.fields]]
name = "description"
label = "Description"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"
[collections.index_file]
[[collections.index_file.fields]]
name = "title"
label = "Title"
[[collections.index_file.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog posts",
"folder": "/content/posts",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "date", "label": "Published Date", "widget": "datetime" },
{ "name": "description", "label": "Description" },
{ "name": "body", "label": "Body", "widget": "richtext" }
],
"index_file": {
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
}
]
}{
collections: [
{
name: "posts",
label: "Blog posts",
folder: "/content/posts",
fields: [
{ name: "title", label: "Title" },
{ name: "date", label: "Published Date", widget: "datetime" },
{ name: "description", label: "Description" },
{ name: "body", label: "Body", widget: "richtext" },
],
index_file: {
fields: [
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
},
],
}Here is an example of full customization. All options are optional.
index_file:
name: _index # File name without a locale or extension. Default: _index
label: Index File # Human-readable file label. Default: Index File
icon: home # Material Symbols icon name. Default: home
fields: # Fields for the index file. If omitted, regular entry fields are used
...
editor:
preview: false # Hide the preview pane if needed. Default: true[index_file]
name = "_index"
label = "Index File"
icon = "home"
# fields would be defined as [[index_file.fields]] elements
# editor configuration
[index_file.editor]
preview = false{
"index_file": {
"name": "_index",
"label": "Index File",
"icon": "home",
"fields": [],
"editor": {
"preview": false
}
}
}{
index_file: {
name: "_index",
label: "Index File",
icon: "home",
fields: [],
editor: {
preview: false,
},
},
}If your regular entry fields and index file fields are identical and you don’t need any options, simply write:
index_file: trueindex_file = true{
"index_file": true
}{
index_file: true,
}Note that the special index file is placed right under the folder, regardless of the collection’s path option. For example, if the path is {{year}}/{{slug}}, a regular entry would be saved as content/posts/2025/title.md, but the index file remains at content/posts/_index.md.
Filtering Entries
With the filter option, you can limit the entries displayed in the Sveltia CMS interface based on specific criteria. This is useful for collections where you want to show only a subset of entries, such as a specific language or category.
This option takes an object with two properties:
field: The name of the field to filter by.valueorpattern: The value that the field must match for an entry to be included.- The
valueproperty checks for exact matches, while thepatternproperty allows for regular expression matching. - The
valuecan be a single value or an array of values. If an array is provided, entries matching any of the values will be included. Ifnullis provided as a value, entries where the field is not set will be included. - The
patternproperty should be a string representing a valid regular expression.
- The
The example below shows how to create two separate collections for English and French blog posts, filtering entries based on the lang field:
collections:
- name: english-posts
label: English Posts
folder: /content/posts
filter: { field: lang, value: en }
fields:
- { name: lang, label: Language, widget: select, options: [en, fr] }
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }
- name: french-posts
label: French Posts
folder: /content/posts
filter: { field: lang, value: fr }
fields:
- { name: lang, label: Language, widget: select, options: [en, fr] }
- { name: title, label: Title }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "english-posts"
label = "English Posts"
folder = "/content/posts"
filter = { field = "lang", value = "en" }
[[collections.fields]]
name = "lang"
label = "Language"
widget = "select"
options = ["en", "fr"]
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"
[[collections]]
name = "french-posts"
label = "French Posts"
folder = "/content/posts"
filter = { field = "lang", value = "fr" }
[[collections.fields]]
name = "lang"
label = "Language"
widget = "select"
options = ["en", "fr"]
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "english-posts",
"label": "English Posts",
"folder": "/content/posts",
"filter": { "field": "lang", "value": "en" },
"fields": [
{ "name": "lang", "label": "Language", "widget": "select", "options": ["en", "fr"] },
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
},
{
"name": "french-posts",
"label": "French Posts",
"folder": "/content/posts",
"filter": { "field": "lang", "value": "fr" },
"fields": [
{ "name": "lang", "label": "Language", "widget": "select", "options": ["en", "fr"] },
{ "name": "title", "label": "Title" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "english-posts",
label: "English Posts",
folder: "/content/posts",
filter: { field: "lang", value: "en" },
fields: [
{ name: "lang", label: "Language", widget: "select", options: ["en", "fr"] },
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
{
name: "french-posts",
label: "French Posts",
folder: "/content/posts",
filter: { field: "lang", value: "fr" },
fields: [
{ name: "lang", label: "Language", widget: "select", options: ["en", "fr"] },
{ name: "title", label: "Title" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}Managing Entry Listings
After creating an entry collection, you might want to customize how entries are displayed in the Sveltia CMS interface. The following options allow you to control various aspects of entry listings.
Summaries
By default, Sveltia CMS uses the title field (or a field defined with the identifier_field option) as the summary for each entry in the listing view.
Sometimes entries might only have a body field without a title field. In such cases, Sveltia CMS will look for a header in the Markdown body field, if it exists, or use the entry slug as a fallback to ensure that the summary is never empty. This behavior supports typical Markdown-based setups like VitePress and Docusaurus.
You can customize the summary displayed for each entry using the summary option. This option accepts a string with template tags that will be replaced with entry-specific values when generating the summary. For example, to display both the title and date of each entry in the summary, you can use the following configuration:
summary: '{{title}} ({{date}})'summary = "{{title}} ({{date}})"{
"summary": "{{title}} ({{date}})"
}{
summary: "{{title}} ({{date}})",
}Basic Markdown syntax is supported in the summary option, including bold, italics and inline code. For example:
summary: '**{{title}}** - _{{date}}_ `{{status}}`'summary = "**{{title}}** - _{{date}}_ `{{status}}`"{
"summary": "**{{title}}** - _{{date}}_ `{{status}}`"
}{
summary: "**{{title}}** - _{{date}}_ `{{status}}`",
}You can use string transformations with these template tags as well. For example:
summary: "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"summary = "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"{
"summary": "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"
}{
summary: "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}",
}The following template tags are supported in the summary option, in addition to slug template tags:
{{dirname}}: The name of the directory containing the entry file, relative to the collectionfolder.{{filename}}: The entry file name without the extension.{{extension}}: The entry file extension.{{commit_author}}: The last commit author of the entry file from Git history (if available).{{commit_date}}: The last commit date of the entry file from Git history (if available).{{locales}}: The enabled locales for the entry when using i18n support.
Known issue
Git commit information is not available with the GitLab backend due to API limitations.
Thumbnails
By default, Sveltia CMS automatically looks for any non-nested, non-empty Image or File field in the entry to use as a thumbnail in the entry listing view. However, you can customize this behavior using the thumbnail option.
collections:
- name: posts
label: Blog Posts
folder: /content/posts
thumbnail: featuredImage
fields:
- { name: title, label: Title }
- { name: featuredImage, label: Featured Image, widget: image }
- { name: body, label: Body, widget: richtext }[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
thumbnail = "featuredImage"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "featuredImage"
label = "Featured Image"
widget = "image"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"thumbnail": "featuredImage",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "featuredImage", "label": "Featured Image", "widget": "image" },
{ "name": "body", "label": "Body", "widget": "richtext" }
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
thumbnail: "featuredImage",
fields: [
{ name: "title", label: "Title" },
{ name: "featuredImage", label: "Featured Image", widget: "image" },
{ name: "body", label: "Body", widget: "richtext" },
],
},
],
}The thumbnail option can take a string or an array of strings representing the field names to be used as thumbnails. The first field that contains a valid image will be used as the thumbnail. For example:
thumbnail: [thumbnailImage, coverImage]thumbnail = ["thumbnailImage", "coverImage"]{
"thumbnail": ["thumbnailImage", "coverImage"]
}{
thumbnail: ["thumbnailImage", "coverImage"],
}A nested field can be specified using dot notation, e.g. heroImage.src. A wildcard in the field name is also supported, e.g. images.*.src, to target images in a list field.
Occasionally, you may not have suitable images for thumbnails. For example, your images may have subtle differences or varied aspect ratios. In that case, you can disable the thumbnail feature by setting the thumbnail option to false or an empty array:
thumbnail: falsethumbnail = false{
"thumbnail": false
}{
thumbnail: false,
}Managing Entry Views
Sveltia CMS provides several options to customize how entries are displayed in the listing view. Users can sort, group, and filter entries based on specific fields to improve navigation and organization.
Sorting
By default, Sveltia CMS supports sorting by title, date, author and description fields if they exist in the collection. If the date and author fields are not present, Sveltia CMS will look for commit date and author information from Git history (if available) to enable sorting by those fields.
You can customize the sortable fields using the sortable_fields option. It accepts an array of field names that you want to enable for sorting in the entry listing view. It also accepts a special slug field to sort entries by their slugs.
The example below shows how to enable sorting by custom fields such as category and nested fields like author.name:
collections:
- name: posts
label: Blog posts
folder: /content/posts
fields:
- { name: title, label: Title }
- { name: published_date, label: Published Date, widget: datetime }
- {
name: author,
label: Author,
widget: object,
fields: [{ name: name, label: Name }, { name: email, label: Email }],
}
- { name: category, label: Category }
- { name: body, label: Body, widget: richtext }
sortable_fields: [title, published_date, author.name, category][[collections]]
name = "posts"
label = "Blog posts"
folder = "/content/posts"
sortable_fields = ["title", "published_date", "author.name", "category"]
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "published_date"
label = "Published Date"
widget = "datetime"
[[collections.fields]]
name = "author"
label = "Author"
widget = "object"
[[collections.fields.fields]]
name = "name"
label = "Name"
[[collections.fields.fields]]
name = "email"
label = "Email"
[[collections.fields]]
name = "category"
label = "Category"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog posts",
"folder": "/content/posts",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "published_date", "label": "Published Date", "widget": "datetime" },
{
"name": "author",
"label": "Author",
"widget": "object",
"fields": [
{ "name": "name", "label": "Name" },
{ "name": "email", "label": "Email" }
]
},
{ "name": "category", "label": "Category" },
{ "name": "body", "label": "Body", "widget": "richtext" }
],
"sortable_fields": ["title", "published_date", "author.name", "category"]
}
]
}{
collections: [
{
name: "posts",
label: "Blog posts",
folder: "/content/posts",
fields: [
{ name: "title", label: "Title" },
{ name: "published_date", label: "Published Date", widget: "datetime" },
{ name: "author", label: "Author", widget: "object", fields: [
{ name: "name", label: "Name" },
{ name: "email", label: "Email" },
] },
{ name: "category", label: "Category" },
{ name: "body", label: "Body", widget: "richtext" },
],
sortable_fields: ["title", "published_date", "author.name", "category"],
},
],
}Extended syntax
Sveltia CMS supports an extended syntax used in Static CMS to define a default sort field and direction. This is useful if you want entries to be sorted by a date field in descending order by default. Here is the same configuration using the extended syntax:
sortable_fields:
fields: [title, published_date, author.name, category]
default:
field: published_date
direction: descendingThe default direction is ascending if not specified.
For backward compatibility with Static CMS, the direction option accepts title case values: Ascending and Descending. However, None is not supported and has the same effect as ascending.
Known issue
Git commit information is not available with the GitLab backend due to API limitations.
Grouping
The view_groups option allows you to group entries in the listing view based on specific field values. This is useful for organizing entries into categories or sections for easier navigation.
The example below demonstrates how to group blog posts by their draft status and by the year extracted from the date field:
collections:
- name: posts
label: Blog posts
folder: /content/posts
fields:
- { name: title, label: Title }
- { name: date, label: Published Date, widget: datetime }
- { name: draft, label: Draft, widget: boolean }
- { name: body, label: Body, widget: richtext }
view_groups:
- field: draft
- label: Drafts
field: date
label: Year
pattern: '\d{4}'[[collections]]
name = "posts"
label = "Blog posts"
folder = "/content/posts"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "date"
label = "Published Date"
widget = "datetime"
[[collections.fields]]
name = "draft"
label = "Draft"
widget = "boolean"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"
[[collections.view_groups]]
label = "Drafts"
field = "draft"
[[collections.view_groups]]
label = "Year"
field = "date"
pattern = "\\d{4}"{
"collections": [
{
"name": "posts",
"label": "Blog posts",
"folder": "/content/posts",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "date", "label": "Published Date", "widget": "datetime" },
{ "name": "draft", "label": "Draft", "widget": "boolean" },
{ "name": "body", "label": "Body", "widget": "richtext" }
],
"view_groups": [
{
"label": "Drafts",
"field": "draft"
},
{
"label": "Year",
"field": "date",
"pattern": "\\d{4}"
}
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog posts",
folder: "/content/posts",
fields: [
{ name: "title", label: "Title" },
{ name: "date", label: "Published Date", widget: "datetime" },
{ name: "draft", label: "Draft", widget: "boolean" },
{ name: "body", label: "Body", widget: "richtext" },
],
view_groups: [
{
label: "Drafts",
field: "draft",
},
{
label: "Year",
field: "date",
pattern: "\\d{4}",
},
],
},
],
}Extended syntax
Sveltia CMS supports an extended syntax used in Static CMS to define a default group. Here is the same configuration using the extended syntax:
view_groups:
groups:
- name: drafts
label: Drafts
field: draft
- name: year
label: Year
field: date
pattern: '\d{4}'
default: yearTo sort the Year group in descending order by date, you can add the sortable_fields property as described in the Sorting section above:
sortable_fields:
fields: [date, title]
default:
field: date
direction: descendingFiltering
The view_filters option allows you to define preset filters that editors can quickly apply to the entry listing view. This is useful for quickly accessing specific subsets of entries based on common criteria.
collections:
- name: posts
label: Blog posts
folder: /content/posts
fields:
- { name: title, label: Title }
- { name: date, label: Published Date, widget: datetime }
- { name: draft, label: Draft, widget: boolean }
- { name: category, label: Category }
- { name: body, label: Body, widget: richtext }
view_filters:
- label: Drafts
field: draft
pattern: true
- label: Posts from 2024
field: date
pattern: '^2024'
- label: Travel or Food
field: category
pattern: travel|food[[collections]]
name = "posts"
label = "Blog posts"
folder = "/content/posts"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "date"
label = "Published Date"
widget = "datetime"
[[collections.fields]]
name = "draft"
label = "Draft"
widget = "boolean"
[[collections.fields]]
name = "category"
label = "Category"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"
[[collections.view_filters]]
label = "Drafts"
field = "draft"
pattern = "true"
[[collections.view_filters]]
label = "Posts from 2024"
field = "date"
pattern = "^2024"
[[collections.view_filters]]
label = "Travel or Food"
field = "category"
pattern = "travel|food"{
"collections": [
{
"name": "posts",
"label": "Blog posts",
"folder": "/content/posts",
"fields": [
{ "name": "title", "label": "Title" },
{ "name": "date", "label": "Published Date", "widget": "datetime" },
{ "name": "draft", "label": "Draft", "widget": "boolean" },
{ "name": "category", "label": "Category" },
{ "name": "body", "label": "Body", "widget": "richtext" }
],
"view_filters": [
{
"label": "Drafts",
"field": "draft",
"pattern": "true"
},
{
"label": "Posts from 2024",
"field": "date",
"pattern": "^2024"
},
{
"label": "Travel or Food",
"field": "category",
"pattern": "travel|food"
}
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog posts",
folder: "/content/posts",
fields: [
{ name: "title", label: "Title" },
{ name: "date", label: "Published Date", widget: "datetime" },
{ name: "draft", label: "Draft", widget: "boolean" },
{ name: "category", label: "Category" },
{ name: "body", label: "Body", widget: "richtext" },
],
view_filters: [
{
label: "Drafts",
field: "draft",
pattern: "true",
},
{
label: "Posts from 2024",
field: "date",
pattern: "^2024",
},
{
label: "Travel or Food",
field: "category",
pattern: "travel|food",
},
],
},
],
}Extended syntax
Sveltia CMS supports an extended syntax used in Static CMS to define a default filter. Here is the same configuration using the extended syntax:
view_filters:
filters:
- name: drafts
label: Drafts
field: draft
pattern: true
- name: posts_2024
label: Posts from 2024
field: date
pattern: '^2024'
- name: travel_or_food
label: Travel or Food
field: category
pattern: travel|food
default: drafts