Replace manual slug entry in the Decap CMS with auto-generation from the content title. This closes the root cause of recurring URL conflicts and slug-format errors, which have required several batch fix campaigns in the repository’s history and caused a Jekyll build failure in July 2026.
Which requirements does this CIP address? REQ-0002 (slug validity, uniqueness, and stability).
Audit results (2026-07-24, scripts/audit-slugs.py): 445 content files across all collections.
redirect_from before migrationpage.slug directly (_layouts/events-category.html)Baseline URL test (2026-07-24, tests/test_slug_urls.py): 31 of the 37 slug URLs return HTTP 200 on the live site. 6 return 404 because their slug field contains characters that cannot form a valid URL (unencoded spaces, leading dash, leading whitespace, @):
_blog_posts/ai-deas-sprints-showcase.md — slug -ai-deas-sprints-showcase (leading dash)_events/ai-for-ops-community-meet-up.md — slug is title text from a different event_events/training-workshop-llm-hands-on-workshop.md — slug is title text from a different event_events/workshop-ai-time-politics-and-ideologies-of-the-future.md — slug is title text from a different event_news/ai2-art-protection-tools-still-leave-creators-at-risk-researchers-say.md — slug has leading whitespace and @ character_policies/policy-brief-refreshing-the-uk's-strategic-approach-to-ai-1.md — slug has apostropheThese 6 are content bugs (broken live pages) and must be fixed first. The remaining 31 are live pages requiring redirect_from entries before migration.
Slugs in the current setup are entered manually by editors in a free-text field. This creates three failure modes, all of which have occurred:
AI for Science Research Showcase instead of ai-for-science-research-showcase), which Jekyll either rejects or normalises inconsistently.slug field and the file name (which is also derived from the slug) can disagree if an editor edits one without the other.The July 2026 conflict between _events/chia-conference-shaping-the-future-of-ai.md and _events/ai-for-science-research-showcase.md is a clear example. Improving hint text (done in commit b623ef0) reduces the incidence but does not eliminate it.
Each content collection in admin/config.yml is configured as:
slug: "" # collection-level: filename derived from frontmatter slug
identifier_field: "slug" # CMS uses slug field as the unique key
fields:
- name: "slug" # editor types this manually
widget: "string"
hint: "lowercase and hyphens only..."
The editor types a slug. The filename becomes that slug. The frontmatter slug and the filename are the same string, but both are under manual control.
Remove the manual slug field from all folder-based content collections. Instead, derive the filename from the title automatically:
slug: "" # filename auto-generated from title
identifier_field: "title" # CMS uses title as the unique key
# no slug field in fields:
Jekyll and the site templates that currently read page.slug from frontmatter will need to fall back to page.title | slugify instead, or a slug field will be computed in a Jekyll plugin/filter.
Option A — Remove slug field entirely, use title-derived URLs everywhere.
Option B — Keep slug field but auto-populate it from title (read-only in CMS).
Option C — Remove slug field, derive URL from title, treat title changes as breaking.
Recommended: Option C.
Existing content already has slug frontmatter fields. These must be handled carefully:
slug equals title | slugify. Where they differ (e.g. custom short slugs), the existing slug takes precedence and a redirect from title | slugify may be needed.slug from admin/config.yml field lists and update identifier_field.page.slug directly to use page.title | slugify or a computed value.slug frontmatter field from existing files only if it exactly matches title | slugify — otherwise leave it in place and let Jekyll use it as an override.Jekyll does not handle redirects natively. The jekyll-redirect-from plugin (already a candidate given the redirect_from fields seen in some existing files) should be confirmed in the Gemfile and used for any titles changed post-publication.
scripts/audit-slugs.py has been run and results recorded in the Summary above. Re-run after any bulk content changes to keep the count accurate._events/chia-conference-shaping-the-future-of-ai.md has a slug for one event and a title for another). Fix the content first, then re-run the audit.redirect_from entry.redirect_from entries — for every remaining real mismatch (legitimate short slug), add redirect_from: ["/title-derived-url/"] to the frontmatter so the title-derived URL will redirect to the existing live URL. This step is a hard gate: do not proceed to step 6 until all real mismatches have a redirect. Required by REQ-0002.jekyll-redirect-from to Gemfile if not already present; document the redirect procedure for future title changes.admin/config.yml — remove slug fields from all folder collections, change collection-level slug templates to "", update identifier_field to "title"._layouts/events-category.html — replace page.slug references (lines 116, 158) with page.title | slugify or equivalent.Existing published URLs are stable as long as the existing slug frontmatter values are preserved in content files. The CMS UI changes (no slug field visible) do not affect the built output. The risk is in step 4 of the migration: if any slug is removed from frontmatter where it differs from title | slugify, that URL changes.
scripts/audit-slugs.py) and run — results in Summary above2026-07-24_fix-data-swap-events-people)redirect_from entries added for all 30 remaining real mismatches (hard gate — REQ-0002)jekyll-redirect-from confirmed in Gemfile and Gemfile.lockadmin/config.yml updated (slug fields removed, templates changed, identifier_field updated)_layouts/events-category.html updated — page.slug → page.name | slugify (lines 116, 158)082c321b623ef063d5434, 620f06c and related