Skip to content

File Formats

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:

yaml
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 }
toml
[[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"
json
{
  "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" }
      ]
    }
  ]
}
js
{
  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; this behavior can be configured using the body_field option in the collection definition.

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:

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

yaml
collections:
  - name: posts
    label: Blog Posts
    folder: /content/posts
    format: json
toml
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "json"
json
{
  "collections": [
    {
      "name": "posts",
      "label": "Blog Posts",
      "folder": "/content/posts",
      "format": "json"
    }
  ]
}
js
{
  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:

json
{
  "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.

  • yml or yaml: YAML files with the yml extension by default.
  • toml: TOML files with the toml extension by default.
  • json: JSON files with the json extension by default.
  • yaml-frontmatter: Markdown files with YAML front matter, the md extension and the --- delimiter by default.
  • toml-frontmatter: Markdown files with TOML front matter, the md extension and the +++ delimiter by default.
  • json-frontmatter: Markdown files with JSON front matter, the md extension 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 to yaml-frontmatter. The md extension and --- delimiter are used by default.
  • raw: Raw text files with the txt extension by default. When using this format, make sure to have only one field named body with the widget type set to code, markdown, richtext or text. 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:

yaml
collections:
  - name: posts
    label: Blog Posts
    folder: /content/posts
    extension: markdown
toml
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
extension = "markdown"
json
{
  "collections": [
    {
      "name": "posts",
      "label": "Blog Posts",
      "folder": "/content/posts",
      "extension": "markdown"
    }
  ]
}
js
{
  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:

yaml
collections:
  - name: posts
    label: Blog Posts
    folder: /content/posts
    format: toml-frontmatter
    frontmatter_delimiter: ~~~ # or [~~~, ~~~]
toml
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "toml-frontmatter"
frontmatter_delimiter = "~~~"
json
{
  "collections": [
    {
      "name": "posts",
      "label": "Blog Posts",
      "folder": "/content/posts",
      "format": "toml-frontmatter",
      "frontmatter_delimiter": "~~~"
    }
  ]
}
js
{
  collections: [
    {
      name: "posts",
      label: "Blog Posts",
      folder: "/content/posts",
      format: "toml-frontmatter",
      frontmatter_delimiter: "~~~",
    },
  ],
}

Body Field for Front Matter Formats

By default, a Markdown field named body is treated as the main content of the file, while other fields are stored in the front matter. This behavior can be configured using the body_field option in the collection definition. The body_field option allows you to specify a different field name for the main content or to store the body content directly in the front matter.

Body Field Name

If you want to use a different field name for the main content, you can specify it using the key property of the body_field option. For example, to use a field named content as the body field:

yaml
collections:
  - name: posts
    label: Blog Posts
    folder: /content/posts
    format: yaml-frontmatter
    body_field:
      key: content
    fields:
      - { name: title, label: Title }
      - { name: content, label: Content, widget: markdown }
toml
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "yaml-frontmatter"
body_field.key = "content"

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

[[collections.fields]]
name = "content"
label = "Content"
widget = "markdown"
json
{
  "collections": [
    {
      "name": "posts",
      "label": "Blog Posts",
      "folder": "/content/posts",
      "format": "yaml-frontmatter",
      "body_field": {
        "key": "content"
      },
      "fields": [
        { "name": "title", "label": "Title" },
        { "name": "content", "label": "Content", "widget": "markdown" }
      ]
    }
  ]
}
js
{
  collections: [
    {
      name: "posts",
      label: "Blog Posts",
      folder: "/content/posts",
      format: "yaml-frontmatter",
      body_field: {
        key: "content",
      },
      fields: [
        { name: "title", label: "Title" },
        { name: "content", label: "Content", widget: "markdown" },
      ],
    },
  ],
}

Inline Body Field

You can set inline: true in the body_field option to store the body content directly in the front matter instead of the file body, while using the body field name for the main content. This is useful when you want to keep all the entry data in the front matter without any content in the file body.

yaml
collections:
  - name: posts
    label: Blog Posts
    folder: /content/posts
    format: yaml-frontmatter
    body_field:
      inline: true
    fields:
      - { name: title, label: Title }
      - { name: body, label: Body, widget: markdown }
toml
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
format = "yaml-frontmatter"
body_field.inline = true

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

[[collections.fields]]
name = "body"
label = "Body"
widget = "markdown"
json
{
  "collections": [
    {
      "name": "posts",
      "label": "Blog Posts",
      "folder": "/content/posts",
      "format": "yaml-frontmatter",
      "body_field": {
        "inline": true
      },
      "fields": [
        { "name": "title", "label": "Title" },
        { "name": "body", "label": "Body", "widget": "markdown" }
      ]
    }
  ]
}
js
{
  collections: [
    {
      name: "posts",
      label: "Blog Posts",
      folder: "/content/posts",
      format: "yaml-frontmatter",
      body_field: {
        inline: true,
      },
      fields: [
        { name: "title", label: "Title" },
        { name: "body", label: "Body", widget: "markdown" },
      ],
    },
  ],
}

With inline: false (the default), the output file would look like this:

yaml
---
title: My Post
---
This is the body of my post.

With inline: true, the output file for a post created with the above configuration would look like this:

yaml
---
title: My Post
body: This is the body of my post.
---