Filename customization
By default, Tina does not enforce strict filename constraints, as operating systems support a wide variety of formats. However, you can enforce custom constraints at the collection level if needed.
Filename Rules
- Filenames must contain only
a-z,A-Z,0-9,-,_,., or/. - Filenames cannot contain spaces
- The filename generated must be unique within the collection
- If the filename starts with
/, it will be treated as an absolute path relative to the collection root- Example:
/foo/bar/blog-postwill be saved as<MyCollectionPath>/post/blog-post.md
- If the filename does not start with
/, it will be treated as relative to the current folder- Example:
bar/blog-postwill be saved as<MyCollectionPath>/<CurrentDirectory>/bar/blog-post.md
Configuration
Property | Description |
|---|---|
| Prevents the user from editing the filename |
| A function that generates the filename based on form values |
| A function that sanitizes the filename input as the user types |
Option A: Sanitizing Input with parse
The parse function allows you to enforce filename constraints within the editor. The provided callback function sanitizes user input in real-time.
Example using parse to enforce snake case
export default defineConfig({//...schema: {collections: [{label: "Blog Posts",ui: {filename: {parse: (filename) => filename.replaceAll(" ","_"),}},name: "post",path: "content/post",format: "mdx",fields: [//...]}],},});
Option B: Generating Filenames with slugify
Use the slugify function to automatically generate filenames based on other fields in the collection.
The
slugifyfunction only applies constraints when the user creates new files. Users can still rename files freely after creation.
Example with slugify and read only
export default defineConfig({//...schema: {collections: [{label: 'Blog Posts',name: 'post',path: 'content/post',format: 'md',ui: {filename: {// if disabled, the editor can not edit the filenamereadonly: true,// Example of using a custom slugify functionslugify: (values) => {// Values is an object containing all the values of the form. In this case it is {title?: string, topic?: string}return `${values?.topic || 'no-topic'}-${values?.title?.toLowerCase().replace(/ /g, '-')}`},},},fields: [{type: 'string',label: 'Title',name: 'title',},{type: 'string',label: 'Topic',name: 'topic',options: ['programming', 'blacksmithing'],},],},],},})
Example with default slugify
If no slugify function is provided and a field has isTitle: true, Tina uses a default slugify function. This removes non-alphanumeric characters and replaces spaces with dashes.
export default defineConfig({//...schema: {collections: [{label: 'Blog Posts',name: 'post',path: 'content/post',format: 'md',fields: [{type: 'string',label: 'Title',name: 'title',// If no slugify function is provided, then by default the "title" field will be used to generate the filenameisTitle: true,required: true,},{type: 'string',label: 'Topic',name: 'topic',options: ['programming', 'blacksmithing'],},],},],},})