Skip to content

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:

yaml
summary: '{{title}} ({{date}})'
toml
summary = "{{title}} ({{date}})"
json
{
  "summary": "{{title}} ({{date}})"
}
js
{
  summary: "{{title}} ({{date}})",
}

Basic Markdown syntax is supported in the summary option, including bold, italics and inline code. For example:

yaml
summary: '**{{title}}** - _{{date}}_ `{{status}}`'
toml
summary = "**{{title}}** - _{{date}}_ `{{status}}`"
json
{
  "summary": "**{{title}}** - _{{date}}_ `{{status}}`"
}
js
{
  summary: "**{{title}}** - _{{date}}_ `{{status}}`",
}

You can use string transformations with these template tags as well. For example:

yaml
summary: "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"
toml
summary = "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"
json
{
  "summary": "{{title}} - {{date | date('DD MMM YYYY')}} {{published | ternary('', '(draft)')}}"
}
js
{
  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 except date-related ones:

  • {{dirname}}: The name of the directory containing the entry file, relative to the collection folder.
  • {{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.

yaml
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 }
toml
[[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"
json
{
  "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" }
      ]
    }
  ]
}
js
{
  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:

yaml
thumbnail: [thumbnailImage, coverImage]
toml
thumbnail = ["thumbnailImage", "coverImage"]
json
{
  "thumbnail": ["thumbnailImage", "coverImage"]
}
js
{
  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:

yaml
thumbnail: false
toml
thumbnail = false
json
{
  "thumbnail": false
}
js
{
  thumbnail: false,
}

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.

yaml
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 }
toml
[[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"
json
{
  "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" }
        ]
      }
    }
  ]
}
js
{
  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.

yaml
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
toml
[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
json
{
  "index_file": {
    "name": "_index",
    "label": "Index File",
    "icon": "home",
    "fields": [],
    "editor": {
      "preview": false
    }
  }
}
js
{
  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:

yaml
index_file: true
toml
index_file = true
json
{
  "index_file": true
}
js
{
  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.
  • value or pattern: The value that the field must match for an entry to be included.
    • The value property checks for exact matches, while the pattern property allows for regular expression matching.
    • The value can be a single value or an array of values. If an array is provided, entries matching any of the values will be included. If null is provided as a value, entries where the field is not set will be included.
    • The pattern property should be a string representing a valid regular expression.

The example below shows how to create two separate collections for English and French blog posts, filtering entries based on the lang field:

yaml
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 }
toml
[[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"
json
{
  "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" }
      ]
    }
  ]
}
js
{
  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" },
      ],
    },
  ],
}