Open erquhart opened 7 years ago
@erquhart how does the slug
entry in collections affect sluggification - is it functional anymore? (I've been working under the assumption that the current behavior is that the title
field is sluggified and turned into the {{slug}}
part of the slug
template).
Yep, that's the default behavior, but date segments can be used for some light slug templating: https://github.com/netlify/netlify-cms/blob/e388ed1721576221523776bfcf25f7124b5f116c/src/backends/backend.js#L27-L44
May happen in tandem with #180.
We currently overwrite any existing entry when a new entry is created that has the same slug. This is probably best fixed along with this issue.
I also think we should throw an error if the slug is going to be blank.
It is a bad idea to silently overwrite entries. If a user creates multiple entries on same day and does not bother about titles, then all entries except last will be lost without any notification. This is easily the worst imaginable behaviour.
I wonder if we should change or prioritize how we visualize the 'title' field to imply it's importance
We're actually looking to eliminate it's importance. Right now it's critical because it's used for automated slug creation, which the user can't see or influence. This issue calls for making slug creation interactive. We could pre-fill with whatever's in a title field, but if there's no field (or the slug is blank for any other reason), the entry would fail validation and could not be saved.
Hi! What's the status on slug editing, anyone working on a suggestion?
@bjrn no one is working this yet, definitely open to someone taking a stab at it.
May I point something? Some SSGs allow us to overwrite the filename based slug. This is speacially useful for Hugo multilingual files. We can have a travel.en.md
file with slug: "travel"
on front matter and a travel.pt.md
file with slug: "viagem"
.
Can we avoid conflicts between the two things?
@robsonsobral I'm not sure what you're saying Netlify CMS should do differently to accommodate for this. Can you explain further?
Update: Your comment on #1063 made it click for me, you're saying filenames and slugs shouldn't be assumed to map 1:1. This is a great point, I'll add it to the OP.
Would you have time to write up some thoughts on what setting both custom slugs and filenames could look like from your perspective?
Actually, @robsonsobral, that already works. If you need a "slug" frontmatter property for Hugo, just add it to your config and the CMS won't pick it up or use it at all. Slugs, for our purposes, are related to the source file name only, and your SSG is concerned with the slug for the built file name.
Thank you for your attention, @erquhart . Please, forgive my late answer.
What will happen if there's a slug
field on front matter, after you allow the edition of slug? How to deal with two fields with the same name?
The editable slug will be an internal value, we won't output it to frontmatter. It should be made available for reuse at some point, though, as requested in #450 and #1063.
As I see it, you can use it in frontmatter if you want, but you could also set your own string. I'm not saying this is exactly how it will work, but a possible config format would be:
# No output to frontmatter.
- {label: "Slug", widget: "slug"}
# Save generated slug in frontmatter.
- {label: "Slug", widget: "slug", name: "slug"}
# Manual slug in frontmatter.
- {label: "Slug", widget: "string", name: "slug"}
Can we customize the field label? If we have a slug
field on frontmatter, we could and with confusing labels.
I'm not expecting there to be a typical field configuration for the slug editor, but I may be underthinking things. Either way, I'd expect output of the slug and other internal/meta values to be made available to fields as placeholder values via https://github.com/netlify/netlify-cms/issues/450. So you could do:
- {name: slug, widget: hidden, default: "{{slug}}"}
@tech4him1 I wouldn't expect a slug widget - here's your example as I'd expect it:
# No output to frontmatter.
# (automatic)
# Save generated slug in frontmatter.
- {label: "Slug", name: "slug", default: "{{slug}}"}
# Manual slug in frontmatter.
# (same as above since the slug is editable as a meta field)
I can't think of a use case for allowing the slug to be configured as a field. You?
This should be tagged high priority or something.
I’ve just had to redo my entire frontmatter because of this single issue. Posts couldn’t be created and it wasn’t even obvious why.
I don’t think there needs to be a super special UI for the slug — perhaps the default behavior, as it is now for title
, would be showing the slug in small lettering underneath that with an edit button? I think something like that is done with WordPress. Otherwise just expose it like any other field.
Starting in v2.0 there is an error message for this -- at least an improvement on the silent breakage we had before.
That’s… not really the case in my experience. If there was no field like title
(even if there was Title
) it would try to publish and throw an error in console and that’s it.
Maybe that should be taken into account too.
@mistermantas That should already be throwing an error. Would you mind opening a new issue with an example config so that I can get that to at least throw an error?
It would also be nice if there was another placeholder like {{random}} generating a random string to use in the slug. I'd like to create a collections with items having no unique field, and just using a slug like slug: "{{year}}-{{month}}-{{day}}-{{hour}}_{{minute}}_{{second}}"
feels a bit risky.
Another possibility to minimize the chance of colliding would be to add milliseconds as another field.
Are we abstracting too much by calling it a slug
instead of a filename
or id
? I think it is important the file name be thought of more as the resource identifier (id
) for the item, not necessarily the slug
value that will be used on a possible website. The primary focus of a CMS is about editing and managing content more than it is about creating a specific website.
In the old days of using prose to make editing GitHub hosted markdown files with front matter easier, the file name was simply a field you filled out when making a new item. Link to prose config docs.
The simplest, most straightforward option for defining a file name is to have a form input field presented to the user. I'd like to see this be the default behavior when no slug
property is provided to the collections config.
The next step in convenience is automatically creating the initial file name based on a template. I suggest passing the values of the fields to the template. So instead of {{ slug }}
it would be {{ title }}
. If you want a date add a date field. If you want the date in a special format use the the field date option for format
in the config. Perhaps we add something like a slugFormat
to the date field config options if the slug needs a different format from how it gets saved to the file. But that gets messy.
create: true
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
fields:
- {label: "Title", name: "title", widget: "string"}
create: true
slug: "{{date}}-{{title}}"
fields:
- {label: "Title", name: "title", widget: "string"}
- {label: "Created Date", name: "date", widget: "datetime", format: "YYYY-MM-DD"}
Fields used in the template should be required
to prevent unexpected results. If you want a "random" element for the slug add a hidden field with a widget that creates a random string portion. Access its value in the template like any other field.
Are we abstracting too much by calling it a slug instead of a filename or id? I think it is important the file name be thought of more as the resource identifier (id) for the item, not necessarily the slug value that will be used on a possible website.
This 👆👆
@webmasterkai I was glad to see your comment as I recently came to the same conclusion: we should not be calling the filename "slug". It's confusing, and I'm betting most folks thumbing this issue up are thinking about the path to their live content and not the filename in the repo. @robsonsobral made a similar point a while back as well.
The more I consider this, the more I realize this whole slug editing thing is almost a non-issue. Static site generators don't care about filenames much (except for extensions), and they typically derive the actual slug and URL from your frontmatter and configuration.
Example I just gave in https://github.com/netlify/netlify-cms/issues/1576#issuecomment-459885997:
For example, let's say you have a Hugo site, a blog post frontmatter might look like this:
--- title: A Clear Performance Comparison between Gatsby and WordPress slug: gatsby-vs-wordpress-performance ---
And your Hugo config would include something like:
permalinks: posts: /:year/:month/:slug/
Anyone think I'm oversimplifying here? Example use cases that require more?
@barthc I'd especially like to hear from you considering your recent work in this area.
@erquhart I think static site generators do care a lot about filenames (and folder names).
The first choice is to use the filename for the output path. See for example in Hugo's Content Organization:
Hugo assumes that the same structure that works to organize your source content is used to organize the rendered site.
The slug
in frontmatter is only meant to override this behavior if needed. Otherwise it's much better to use the folder and filename as a path. Unrelated file names would make it unnecessary hard to find the content file for a specific blog post, for example.
Not only file names matter but also folder names. As is discussed in #1472 with so called Page Bundles, assets and markdown files are stored in a folder. The entire folder will be copied and rendered to the final site.
content/
├── posts
│ ├── my-post-1
│ │ ├── index.md
│ │ └── post-image.jpg
│ ├── my-post-2
│ │ ├── index.md
│ │ └── post-image.jpg
│ ├── _index.md
│ └── overview-image.jpg
will render to:
public/
├── posts
│ ├── my-post-1
│ │ ├── index.html
│ │ └── post-image.jpg
│ ├── my-post-2
│ │ ├── index.html
│ │ └── post-image.jpg
│ ├── index.html
│ └── overview-image.jpg
For sluggification to work with this, Netlify CMS would need to allow changing the folder name.
That's a very good point, thanks for laying it out. I guess I mostly see sites using custom permalinks via frontmatter rather than going with filename driven defaults, so it didn't seem that relevant, but it's a smart default, agreed.
Update:
Some SSG's, like Jekyll, respect a slug
value in the frontmatter. Until recently the {{slug}}
built in placeholder made it impossible to reference a field named slug in your slug
configuration, but as of Netlify CMS 2.4.2 you can now do {{fields.slug}}
to reference a field by that name. That means you can control your filename in a predictable way:
collections:
- name: posts
folder: posts
slug: {{fields.slug}}
fields:
- {name: title, label: Title}
- {name: slug, label: Slug}
- {name: body, label: Body, widget: markdown}
Note: this does not provide any way to change the filename after the initial save.
It's manual, but it's technically a minimum viable approach that satisfies the goals of this issue:
slug
configWe should keep the issue open for a more automated approach that's workable for non-technical editors, but this is at least a good stop gap for folks that need it.
@erquhart that approach do not allow the field to be sluggified automatically from the title, it will need to be manually set each time. Can you please confirm. Ideally the field should be visible and updated once the title is set, but in this case if is empty it will fail, and will force manual entry. In a different note, without talking about slug update, it will be nice to be able to create a field with the contents of the slug field just like path : "/example/{{slug}}"
@erodrig yep, just providing a newly available stopgap. Issue remains open for an automated solution.
Sent with GitHawk
What's the status on this? Can anyone provide an update? Is it at all possible to save the relation value as the slug
?
That's always been possible, just use the name of your relation field in the slug template. Let's say you have a relation field named "relation"
, your slug template would be {{relation}}
.
Tied this to https://github.com/netlify/netlify-cms/issues/1767, because files without frontmatter have their own particular sluggification issues.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I want to point out that the introduction of the path
parameter introduces the problem of how to handle slug/frontmatter changes after the first save. E.g. /pages/{:year}/entry.md
or /roster/{:team}/player.md
remain at their current location, even if the dynamic portion of their path changes.
Hi @adrian5, thank you for pointing this out. I think the issue you mentioned is already present with the slug
configuration as you could do slug: {{year}}-{{title}}
but probably more prominent when using path
.
I stumbled across this issue myself. Now that the config, entry data and collection is available to all control widgets (#3672) I was able to implement a custom slug control widget that allows the following:
... # whatever collection
- slug: '{{field.slug}}'
- fields:
- name: title
label: Title
widget: string
- name: slug
label: Slug
widget: slug
slug: 'custom-slug-{{title}}'
slug
value field with a custom slug
widget (that's basically a string widget) that can be used for the entry slug with fields.slug
slug
is automatically updated and correctly slugified according to the slug
pattern and the root slug
configurationThis works very well for me (I think at least). It still does not provide a way for a user to forcefully update the filename through the slug though.
Once it is a bit more polished I will open a PR (in the next few days) and then I would love to continue this discussion.
@hanneskuettner I look forward to your PR. In the mean time, I came up with a fairly decent solution that might help others.
I used Nested Collections to basically give me the same effect since the slug (file name) is set via the meta.path
field.
collections:
- name: 'pages'
create: true
label: 'Page'
folder: 'src/content/pages'
nested: { depth: 100, summary: '{{meta.path}}' }
meta: { path: { widget: string, label: 'Path', index_file: 'index' } }
fields:
- label: 'Title'
name: 'title'
widget: 'string'
- label: 'Body'
name: 'body'
widget: 'markdown'
And then if I add two items in the collection with paths set to: dir-a/dir-b/item-a
and dir-a/dir-c/item-b
This results in a src/content/pages
directory looking like:
src/content/pages:
dir-a:
dir-b:
item-a:
- index.md
dir-c:
item-b:
- index.md
I'm using Gatsby so it's reasonably straightforward to generate slugs at build time using the technique from this guide.
Here's the thing: Without keeping the filename in sync with the slug, it's impossible to look up a single post without parsing the frontmatter of all files in the same collection. E.g., if my app wants the post with slug what-a-nice-post
, the app needs to load all of the posts into memory. This kinda sucks when used alongside NextJS, which supports incremental static generation as well as incremental cache invalidation.
For this reason—and since URL slugs must be unique anyway—I think it makes more sense to update the filename whenever the slug changes.
Regarding how and when the slug changes, I like @hanneskuettner approach. The slug should stop auto-updating once the document is published (which happens at varying times depending on if you use the editorial workflow). After that, a notice is fair, as well as preventing a user from overwriting another file or making a change that would cause merge errors (if there are multiple editorial edits open on the file that would be renamed).
Honestly, I think Wordpress really nails their slug behavior, especially in cases where extra bits are added to the complete path. #377 has a screenshot that at least partly shows this behavior.
@hanneskuettner If you would, I'd very much appreciate seeing your work on that slug field. :)
What's the progress on this?
Hi @michalhudecek this issue is not an easy lift. Do you have a specific use case you're trying to solve?
I would like to make the slug editable with a warning for editors that this might break already shared links.
I would like to make the slug editable with a warning for editors that this might break already shared links.
Will the approach in https://github.com/netlify/netlify-cms/issues/445#issuecomment-621700949 satisfy your use case?
Yes, that seems like a perfect solution.
Just want to share. Problem in my case is that slug does not sync with the title.
I use jekyll with netlify cms. When creating a page in Netlify "Hello World Page" this will be saved as "hello-world-page-md". In jekyll this will be generated to "/hello-world-page.html" when the site is built. Problem is when changing the title of the page to "Hello Again World", the markdown is still "hello-world-page.md and therfore the generated page will be "/hello-world-page.html".
This causing problems with url not reflecting the page title. I think it is problematic to share a url not reflecting the content of the page.
Jekyll can overwrite the generated url with slug variable provided in font matter. Problem is i cant use jekylls liquid variables in font matter. So it wont be dynamic.
I could create a field "slug" in the netlify collection. But the only way that would work for me was if it mirrored title, and the field was hidden. So the solution described here might work for me aswell.
Problem in my case is that slug does not sync with the title.
Updating slugs has to be an explicit action. Otherwise, content authors would unknowingly break backlinks all the time. You’d have to account for the update by generating redirect rules for the web server. Traditional CMSs—which may have access to the web server and thus could generate redirects—don’t even do this.
If you have access to the code (i.e. you’re not a non-technical content author), the most straightforward way is to just rename the file.
@tylerbrostrom I think it should be explicit as well, but I'd much rather see this change happen in pieces than it be delayed another 4 years. The vast majority of users only have one content editor.
@tylerbrostrom i agree.
But this may result in a dillemma.
Not having relevant keywords in domain / url could hurt your relevant search scoore, preventing you from getting the 1st spot in search lists.
But as you mentions, broken backlinks may be a bigger problem. Backlinks also impact the search scoore.
I cant prove that this is the case. If anyone can confirm that the url does not affect the search result, then I have no idea what is best.
Something crossed my mind. With netlify you can create a _redirects file in root. May be complicated. But if Netlify CMS could manage a file like that. Then changing the slug wouldnt be a problem with already shared links. Just a crazy thought.
@andreasbalevik I'd prefer a formerSlugs array on the documents themselves for the user to handle based on platform. Some will need redirects, some won't because they're the location of new documents.
Default sluggification is simplistic, relying on a title field and performing no inference whatsoever.
With no field named "title", entries currently fail to save.
The ideal fix is to simply make slugs editable in the editor UI.
Considerations: