Skip to content

Validate TinaCMS content slugs to reject invalid URL characters #185

@jakebromberg

Description

@jakebromberg

Problem

The blog post at content/blog/boy-harsher-at-cat's-cradle.md had an apostrophe in its filename. When @tinacms/cli was bumped past 2.x (see #177), the new validator rejected the path with:

Error: Unable to fetch
Invalid path: relativePath contains invalid characters

This broke prerender of /blog/boy-harsher-at-cat's-cradle and the entire production build.

The file was renamed to boy-harsher-at-cats-cradle.md as part of #177 to unblock the dependency bump, matching the convention used by every other Cat's Cradle post in the collection.

Why this happened

Nothing in the TinaCMS schema or our editorial workflow prevented an editor from typing a slug (or a title that gets slugified) containing an apostrophe, em-dash, parentheses, or other characters that are invalid in URL paths or that downstream tooling rejects. The editor saved the file; it built fine under the old cli; it silently became a landmine when the cli's validation tightened.

Proposal

Add a guardrail somewhere upstream of the build. Options, in rough order of preference:

  1. TinaCMS schema-level filename/slug validation on the blog and archive collections — restrict slugs to [a-z0-9-]+ (lowercase kebab-case). This catches the problem at edit time, in the CMS UI, before the file is even committed.
  2. Pre-commit / CI check that scans content/**/*.md filenames and fails on any character outside the allowed set. Cheaper to implement but only catches after-the-fact.
  3. Both — schema validation prevents new bad slugs; CI check is the safety net.

Acceptance

  • Editors can no longer save a TinaCMS post with an invalid slug character.
  • CI fails fast (with a clear message) if such a file ever lands in content/.
  • Existing content audited and renamed if any other files have this latent issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions