How-Tos
This section provides practical guides on how to implement common features and use cases with Sveltia CMS.
Using Entry Tags for Categorization
If you write blog posts, for example, you may want to categorize them with taxonomies, often called tags, categories, labels or keywords. With Sveltia CMS, there are several ways to implement this feature, depending on your needs.
If you don’t have a predefined list of tags, you can use a simple List field. This configuration will produce a newline-separated text field where users can enter tags freely:
collections:
- name: posts
label: Blog Posts
label_singular: Blog Post
folder: /content/posts
fields:
- name: title
label: Title
- name: tags
label: Tags
widget: list
- name: body
label: Body
widget: richtext[[collections]]
name = "posts"
label = "Blog Posts"
label_singular = "Blog Post"
folder = "/content/posts"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "tags"
label = "Tags"
widget = "list"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"label_singular": "Blog Post",
"folder": "/content/posts",
"fields": [
{
"name": "title",
"label": "Title"
},
{
"name": "tags",
"label": "Tags",
"widget": "list"
},
{
"name": "body",
"label": "Body",
"widget": "richtext"
}
]
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
label_singular: "Blog Post",
folder: "/content/posts",
fields: [
{
name: "title",
label: "Title",
},
{
name: "tags",
label: "Tags",
widget: "list",
},
{
name: "body",
label: "Body",
widget: "richtext",
},
],
},
],
}If you have a small number of predefined tags, you can use a Select field. This configuration will produce a dropdown list where users can select one or more tags:
fields:
- name: tags
label: Tags
widget: select
multiple: true
options:
- { label: Travel, value: travel }
- { label: Food, value: food }
- { label: Technology, value: technology }
- { label: Lifestyle, value: lifestyle }[[fields]]
name = "tags"
label = "Tags"
widget = "select"
multiple = true
[[fields.options]]
label = "Travel"
value = "travel"
[[fields.options]]
label = "Food"
value = "food"
[[fields.options]]
label = "Technology"
value = "technology"
[[fields.options]]
label = "Lifestyle"
value = "lifestyle"{
"fields": [
{
"name": "tags",
"label": "Tags",
"widget": "select",
"multiple": true,
"options": [
{ "label": "Travel", "value": "travel" },
{ "label": "Food", "value": "food" },
{ "label": "Technology", "value": "technology" },
{ "label": "Lifestyle", "value": "lifestyle" }
]
}
]
}{
fields: [
{
name: "tags",
label: "Tags",
widget: "select",
multiple: true,
options: [
{ label: "Travel", value: "travel" },
{ label: "Food", value: "food" },
{ label: "Technology", value: "technology" },
{ label: "Lifestyle", value: "lifestyle" },
],
},
],
}If you want more flexibility, you can create a separate collection for tags and reference it using a Relation field from your blog post collection. This approach allows you to:
- Add many tags without bloating the configuration file
- Manage tags in one place within the CMS
- Reuse tags across multiple collections
- Add a description, image and other details to each tag (if you have tag index pages)
- Localize tags with i18n support enabled
This configuration will also produce a dropdown list where users can select one or more tags:
fields:
- name: tags
label: Tags
widget: relation
multiple: true
collection: tags
search_fields: [title]
display_fields: [title]
value_field: '{{slug}}'[[fields]]
name = "tags"
label = "Tags"
widget = "relation"
multiple = true
collection = "tags"
search_fields = ["title"]
display_fields = ["title"]
value_field = "{{slug}}"{
"fields": [
{
"name": "tags",
"label": "Tags",
"widget": "relation",
"multiple": true,
"collection": "tags",
"search_fields": ["title"],
"display_fields": ["title"],
"value_field": "{{slug}}"
}
]
}{
fields: [
{
name: "tags",
label: "Tags",
widget: "relation",
multiple: true,
collection: "tags",
search_fields: ["title"],
display_fields: ["title"],
value_field: "{{slug}}",
},
],
}And here is an example of the corresponding tag collection:
collections:
- name: tags
label: Tags
label_singular: Tag
folder: /content/tags
fields:
- name: title
label: Title
- name: description
label: Description
widget: text
required: false
- name: image
label: Image
widget: image
required: false[[collections]]
name = "tags"
label = "Tags"
label_singular = "Tag"
folder = "/content/tags"
[[collections.fields]]
name = "title"
label = "Title"
[[collections.fields]]
name = "description"
label = "Description"
widget = "text"
required = false
[[collections.fields]]
name = "image"
label = "Image"
widget = "image"
required = false{
"collections": [
{
"name": "tags",
"label": "Tags",
"label_singular": "Tag",
"folder": "/content/tags",
"fields": [
{
"name": "title",
"label": "Title"
},
{
"name": "description",
"label": "Description",
"widget": "text",
"required": false
},
{
"name": "image",
"label": "Image",
"widget": "image",
"required": false
}
]
}
]
}{
collections: [
{
name: "tags",
label: "Tags",
label_singular: "Tag",
folder: "/content/tags",
fields: [
{
name: "title",
label: "Title",
},
{
name: "description",
label: "Description",
widget: "text",
required: false,
},
{
name: "image",
label: "Image",
widget: "image",
required: false,
},
],
},
],
}Note that it’s not currently possible to add new tags on the fly while editing a blog post. You have to create them in the tag collection first. This issue will be resolved in the future. (#493)
Editing Raw Text Files
Sveltia CMS allows users to edit raw text files without any front matter, such as JSON, XML, or CSV files. To achieve this, you can use the raw format in a file collection with a single body field configured with the appropriate widget type: code, markdown, richtext or text.
Here is an example configuration for editing the README.md and package.json files:
collections:
- name: root_files
label: Root Files
editor:
preview: false
files:
- name: readme
label: README
file: README.md
format: raw
fields:
- name: body
label: README.md
widget: richtext
- name: package_json
label: package.json
file: package.json
format: raw
fields:
- name: body
label: package.json
widget: code
output_code_only: true
allow_language_selection: false
default_language: json[[collections]]
name = "root_files"
label = "Root Files"
[collections.editor]
preview = false
[[collections.files]]
name = "readme"
label = "README"
file = "README.md"
format = "raw"
[[collections.files.fields]]
name = "body"
label = "README.md"
widget = "richtext"
[[collections.files]]
name = "package_json"
label = "package.json"
file = "package.json"
format = "raw"
[[collections.files.fields]]
name = "body"
label = "package.json"
widget = "code"
output_code_only = true
allow_language_selection = false
default_language = "json"{
"collections": [
{
"name": "root_files",
"label": "Root Files",
"editor": {
"preview": false
},
"files": [
{
"name": "readme",
"label": "README",
"file": "README.md",
"format": "raw",
"fields": [
{
"name": "body",
"label": "README.md",
"widget": "richtext"
}
]
},
{
"name": "package_json",
"label": "package.json",
"file": "package.json",
"format": "raw",
"fields": [
{
"name": "body",
"label": "package.json",
"widget": "code",
"output_code_only": true,
"allow_language_selection": false,
"default_language": "json"
}
]
}
]
}
]
}{
collections: [
{
name: "root_files",
label: "Root Files",
editor: {
preview: false,
},
files: [
{
name: "readme",
label: "README",
file: "README.md",
format: "raw",
fields: [
{
name: "body",
label: "README.md",
widget: "richtext",
},
],
},
{
name: "package_json",
label: "package.json",
file: "package.json",
format: "raw",
fields: [
{
name: "body",
label: "package.json",
widget: "code",
output_code_only: true,
allow_language_selection: false,
default_language: "json",
},
],
},
],
},
],
}Editing Site Deployment Configuration Files
Sveltia CMS allows users to edit files without extensions. Examples include _headers and _redirects, which are used by some static site hosting providers, such as Netlify, GitLab Pages and Cloudflare Pages.
Since the body field is saved without the field name when using the default yaml-frontmatter format, you can use the following configuration to edit these files in the Content Editor. Or you can explicitly set the format option to raw, just like in the previous section.
collections:
- name: config
label: Site Configuration
editor:
preview: false
files:
- name: headers
label: Headers
file: static/_headers # The path varies by framework
fields:
- name: body
label: Headers
widget: code # Can also be `text`
output_code_only: true
allow_language_selection: false
- name: redirects
label: Redirects
file: static/_redirects # The path varies by framework
fields:
- name: body
label: Redirects
widget: code # Can also be `text`
output_code_only: true
allow_language_selection: false[[collections]]
name = "config"
label = "Site Configuration"
[collections.editor]
preview = false
[[collections.files]]
name = "headers"
label = "Headers"
file = "static/_headers"
[[collections.files.fields]]
name = "body"
label = "Headers"
widget = "code"
output_code_only = true
allow_language_selection = false
[[collections.files]]
name = "redirects"
label = "Redirects"
file = "static/_redirects"
[[collections.files.fields]]
name = "body"
label = "Redirects"
widget = "code"
output_code_only = true
allow_language_selection = false{
"collections": [
{
"name": "config",
"label": "Site Configuration",
"editor": {
"preview": false
},
"files": [
{
"name": "headers",
"label": "Headers",
"file": "static/_headers",
"fields": [
{
"name": "body",
"label": "Headers",
"widget": "code",
"output_code_only": true,
"allow_language_selection": false
}
]
},
{
"name": "redirects",
"label": "Redirects",
"file": "static/_redirects",
"fields": [
{
"name": "body",
"label": "Redirects",
"widget": "code",
"output_code_only": true,
"allow_language_selection": false
}
]
}
]
}
]
}{
collections: [
{
name: "config",
label: "Site Configuration",
editor: {
preview: false,
},
files: [
{
name: "headers",
label: "Headers",
file: "static/_headers",
fields: [
{
name: "body",
label: "Headers",
widget: "code",
output_code_only: true,
allow_language_selection: false,
},
],
},
{
name: "redirects",
label: "Redirects",
file: "static/_redirects",
fields: [
{
name: "body",
label: "Redirects",
widget: "code",
output_code_only: true,
allow_language_selection: false,
},
],
},
],
},
],
}Creating Conditional Fields
Sometimes, you may want to create your content model in a flexible way. Sveltia CMS does not support dependent fields yet, but you can achieve similar functionality using variable types in List and Object fields. This approach lets you make fields that can hold different types of data based on what the user chooses. Look at the documentation for each field to see examples.
Rendering Soft Line Breaks as Hard Line Breaks in Markdown
In the rich text editor, pressing Shift+Enter inserts a soft line break (\n). We can’t change the behavior to add a hard line break (<br>) — it’s a limitation of the underlying Lexical framework. However, if you look at the preview, you may notice that soft line breaks are rendered as hard line breaks. That’s because the preview is using the Marked library with the breaks option enabled, which mimics how comments are rendered on GitHub.
Chances are the Markdown parser you use for your frontend can do the same:
- markdown-it (used in Eleventy and VitePress) also has the
breaksoption - remarkable also has the
breaksoption - Showdown has the
simpleLineBreaksoption - goldmark (used in Hugo) has the
html.WithHardWrapsoption - kramdown (used in Jekyll) has the
hard_wrapoption with the GFM parser - remark (used in Astro) offers a plugin
- micromark clarifies it doesn’t have such an option and recommends alternatives