Skip to content

Feature Request: Improve Slug / Filename UX Without Creating Duplicate Sources of Truth #636

@smn-cds

Description

@smn-cds

I’m struggling with the current options in Sveltia CMS to properly guide users when defining filenames (slugs), especially when the filename itself is the authoritative identifier and should not be duplicated inside the file.

Use Case

I have two collections: languages and articles.

1. Languages Collection

Each language is stored as a JSON file named by its BCP-47 language code:

src/
  content/
    languages/
      de.json
      en.json
      es.json

Each file contains metadata about the language (e.g. native name, text direction, etc.).

The filename without extension (e.g. de) is the canonical identifier.

2. Articles Collection

Articles reference languages via Astro content collections using the filename (without .json):

---
language: de
---
# Foo bar

This works well technically — but creating new languages through Sveltia CMS introduces UX and data consistency problems.

The Core Problem

When creating a new language definition in Sveltia CMS:

  • The filename must be a valid BCP-47 code.
  • The filename is the only source of truth.
  • I do not want to duplicate that value inside the JSON.
  • Users need guidance (label, hint, validation, possibly a custom widget).

Currently, I see only two ways to achieve this — both with significant drawbacks.

Current Approaches & Limitations

Option 1: Use a bcp47 Field to Generate the Slug

collections:
  - name: languages
    slug: "{{bcp47}}"
    fields:
      - name: bcp47
        label: BCP47 language code
        widget: string

Pros

  • Full control over label, hint, and validation.
  • Can later swap in a custom widget.

Cons

  • Creates two sources of truth:
    • The filename
    • The bcp47 field inside the JSON
  • If users later edit the bcp47 field, the filename is not updated.
  • The value is only needed to generate the filename — I don’t actually want it stored in the JSON.

This introduces inconsistency risk and unnecessary data duplication.

Option 2: Use {{fields._slug}} to Expose the Slug Editor

slug: "{{fields._slug}}"

This avoids duplicating data and keeps the filename as the single source of truth.

Pros

  • No duplicated identifier inside the file.
  • Clean data model.

Cons

  • No control over:
    • Label
    • Hint/description
    • Validation pattern
    • Custom widget
  • No way to guide users toward valid BCP-47 codes.

This results in poor UX because the slug editor is not configurable.

What’s Missing

There’s currently no way to:

  • Define filename behavior independently from file content.
  • Customize the slug editor like a normal field.
  • Provide validation, hints, or custom widgets for filenames.

This limitation affects not only this language example but other similar use cases.

Proposed Improvements

1. Make the Slug Editor Configurable

Option A: Allow slug to be a field definition

Allow slug to accept either a string template or a field definition.

collections:
  - name: languages
    slug:
      label: BCP-47 code
      hint: "Must be a valid BCP-47 language code (e.g. en, de, es-ES)"
      widget: string
      pattern: "^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$"
    fields:
      # other fields...

This keeps the filename as the single source of truth while allowing full UX control.

Option B: Allow Explicit Assignment of a Field to the Slug

collections:
  - name: languages
    slug: "{{fields._slug}}"
    fields:
      - name: _slug
        label: BCP-47 code
        hint: "Must be a valid BCP-47 language code"
        pattern: "^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$"

This makes _slug a first-class configurable field.

2. Support Create-Only (Transient) Fields

Another possible approach would be to support fields that:

  • Are only visible during creation.
  • Are not stored in the resulting file.
  • Are used only to generate the slug.

Example:

collections:
  - name: languages
    slug: "{{bcp47}}"
    fields:
      - name: bcp47
        create_only: true
        label: BCP-47 code
        hint: "Used to generate the filename"

This avoids duplicated data while still allowing validation and custom UX during creation.

The naming (transient, create_only, etc.) would need thoughtful consideration.

Why This Matters

This is not just about BCP-47 codes.

Many content models rely on:

  • Filenames as canonical IDs.
  • Referential integrity between collections.
  • Clean data without redundant identifiers.
  • Strong UX guidance for non-technical users.

Improving slug configurability would:

  • Prevent data inconsistencies.
  • Improve editor experience.
  • Enable custom validation and widgets.
  • Reduce workaround patterns.
  • Keep content models clean and predictable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions