Skip to content

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.

When the summary option is defined for a collection, Sveltia CMS also enables sorting by entry summaries. This allows you to sort entries based on the customized summary content, which can include multiple fields and string transformations.

When the reorder option is enabled for a collection, Sveltia CMS enables manual sorting of entries in the listing view. This allows users to drag and drop entries to reorder them as needed.

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:

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

yaml
sortable_fields:
  fields: [title, published_date, author.name, category]
  default:
    field: published_date
    direction: descending

The 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:

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

yaml
view_groups:
  groups:
    - name: drafts
      label: Drafts
      field: draft
    - name: year
      label: Year
      field: date
      pattern: '\d{4}'
  default: year

The default option has to be the name of one of the groups; any other name is reported as a config validation error on the login screen, as the collection would otherwise open ungrouped.

To sort the Year group in descending order by date, you can add the sortable_fields property as described in the Sorting section above:

yaml
sortable_fields:
  fields: [date, title]
  default:
    field: date
    direction: descending

A named view group can also be used with the reorder option to let editors reorder entries within their own group.

Grouping by a Comparison

A view group can also split the entries by a comparison, using the same options as a view filter. The entries satisfying the condition are grouped under the group’s label, and the other entries under “Other”. For example, the following group lists the upcoming events first, followed by the past and undated ones:

yaml
view_groups:
  - label: Upcoming
    field: date
    gte: '{{today}}'

Filtering

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.

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

yaml
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

The default option has to be the name of one of the filters; any other name is reported as a config validation error on the login screen, as the collection would otherwise open unfiltered.

Comparing Values

A view filter can compare the field value with a given value instead of, or in addition to, matching a pattern. This makes it possible to filter entries by a date, such as upcoming and past events, or by a number, such as products above a certain price. The following options are available:

OptionDescription
eqThe field value has to be equal to the given value.
neThe field value has to be different from the given value.
ltThe field value has to be less than the given value.
lteThe field value has to be less than or equal to the given value.
gtThe field value has to be greater than the given value.
gteThe field value has to be greater than or equal to the given value.
inThe field value has to be equal to one of the given values, defined as an array.
not_inThe field value has to be different from all the given values, defined as an array.

The value of a DateTime field is compared as a date, so the given value has to be in the same format as the field value, or one of the following template tags:

TagDescription
{{now}}The current date and time.
{{today}}The current date in the YYYY-MM-DD format. Use this rather than {{now}} with a date-only field, so that an entry dated today is included in a gte comparison.
{{year}}, {{month}}, {{day}}, {{hour}}, {{minute}}, {{second}}The parts of the current date and time, which can also be used in a pattern, e.g. ^{{year}} for the entries of this year.

The tags are resolved in the user’s local time zone whenever the entry list is updated, and every minute while such a filter or group is applied, so a filter like “Upcoming events” keeps working without any change to the configuration.

A number field value and a numeric given value are compared as numbers; any other value is compared as a string. An entry without a value for the field only matches ne and not_in. When several options are defined for one filter, all of them have to be satisfied.

The comparison options can also be used with the extended syntax described above, for example to apply the “Upcoming” filter by default:

yaml
view_filters:
  filters:
    - name: upcoming
      label: Upcoming
      field: date
      gte: '{{today}}'
    - name: past
      label: Past
      field: date
      lt: '{{today}}'
  default: upcoming

The example below defines the filters for a list of events:

yaml
collections:
  - name: events
    label: Events
    folder: /content/events
    fields:
      - { name: title, label: Title }
      - { name: date, label: Date, widget: datetime, time_format: false }
      - { name: capacity, label: Capacity, widget: number }
      - { name: status, label: Status, widget: select, options: [scheduled, cancelled] }
    view_filters:
      - label: Upcoming
        field: date
        gte: '{{today}}'
      - label: Past
        field: date
        lt: '{{today}}'
      - label: This year
        field: date
        pattern: '^{{year}}'
      - label: Large venues
        field: capacity
        gte: 100
      - label: Not cancelled
        field: status
        ne: cancelled
toml
[[collections]]
name = "events"
label = "Events"
folder = "/content/events"

[[collections.fields]]
name = "title"
label = "Title"

[[collections.fields]]
name = "date"
label = "Date"
widget = "datetime"
time_format = false

[[collections.fields]]
name = "capacity"
label = "Capacity"
widget = "number"

[[collections.fields]]
name = "status"
label = "Status"
widget = "select"
options = ["scheduled", "cancelled"]

[[collections.view_filters]]
label = "Upcoming"
field = "date"
gte = "{{today}}"

[[collections.view_filters]]
label = "Past"
field = "date"
lt = "{{today}}"

[[collections.view_filters]]
label = "This year"
field = "date"
pattern = "^{{year}}"

[[collections.view_filters]]
label = "Large venues"
field = "capacity"
gte = 100

[[collections.view_filters]]
label = "Not cancelled"
field = "status"
ne = "cancelled"
json
{
  "collections": [
    {
      "name": "events",
      "label": "Events",
      "folder": "/content/events",
      "fields": [
        { "name": "title", "label": "Title" },
        { "name": "date", "label": "Date", "widget": "datetime", "time_format": false },
        { "name": "capacity", "label": "Capacity", "widget": "number" },
        { "name": "status", "label": "Status", "widget": "select", "options": ["scheduled", "cancelled"] }
      ],
      "view_filters": [
        {
          "label": "Upcoming",
          "field": "date",
          "gte": "{{today}}"
        },
        {
          "label": "Past",
          "field": "date",
          "lt": "{{today}}"
        },
        {
          "label": "This year",
          "field": "date",
          "pattern": "^{{year}}"
        },
        {
          "label": "Large venues",
          "field": "capacity",
          "gte": 100
        },
        {
          "label": "Not cancelled",
          "field": "status",
          "ne": "cancelled"
        }
      ]
    }
  ]
}
js
{
  collections: [
    {
      name: "events",
      label: "Events",
      folder: "/content/events",
      fields: [
        { name: "title", label: "Title" },
        { name: "date", label: "Date", widget: "datetime", time_format: false },
        { name: "capacity", label: "Capacity", widget: "number" },
        { name: "status", label: "Status", widget: "select", options: ["scheduled", "cancelled"] },
      ],
      view_filters: [
        {
          label: "Upcoming",
          field: "date",
          gte: "{{today}}",
        },
        {
          label: "Past",
          field: "date",
          lt: "{{today}}",
        },
        {
          label: "This year",
          field: "date",
          pattern: "^{{year}}",
        },
        {
          label: "Large venues",
          field: "capacity",
          gte: 100,
        },
        {
          label: "Not cancelled",
          field: "status",
          ne: "cancelled",
        },
      ],
    },
  ],
}