Emulating Jekyll Permalinks

No. All the posts are in /posts/

Are you saying that I would need to change the “category: thing” in each file to “slug: thing” then use :slug?

As a note, I wrote a script real quick that takes the “category: thing” and moves the posts to /content/posts/thing/filename

However when using “/:section/:year/:month/:day/:filename/” the permalink shows as “/posts/year/month/day/filename”

I would expect it to go to “/thing/year/month/day/filename” or even perhaps “posts/thing/year/month/day/filename”.

Am I misunderstanding how :section works?

:section represents only the top level Section in this case posts

:sections is probably what you would want to use since it represents the content’s sections hierarchy.


I just tried :sections and it still is showing “/posts/etc…”

I have the following:

  posts: /:sections/:year/:month/:day/:filename/

and the posts are showing up at /posts/year/month/day/filename

The posts itself are under /posts/category/ where category is the category.

Here is a concrete example:

On disk I have this: /posts/general/2017-06-27-Mobile-Updates

With the permalinks as written above, this is the url I’m getting: http://baseurl/posts/2017/06/27/2017-06-27-Mobile-Updates.html

Everything past the year (2017) is correct for what I need. However I’m trying to get it to do this: http://baseurl/general/2017/06/27/2017-06-27-Mobile-Updates.html while maintaining the content/posts directory.

Any further ideas on this?

How many categories are you looking into migrating?

Also what you want to do is a hard problem. I admit that when I first replied I hadn’t quite realized that what you’re really asking is a way to override the name of a section from the Permalinks.

If you search the forum with the above keywords you will see that this issue has come up before like over here

I’m looking to migrating around 50 categories.

Thank you for the link. I’ll investigate that as well.

That’s quite a lot of categories for you to configure their permalinks.

In any case I submitted a PR in the Hugo Docs repo for Nested Taxonomies, you might find parts of it useful for your use case.

Awesome, thank you very much. Looking at the commit, it appears that I should be able to write a script that generates the necessary setup for me.

If/When I get this working, I’l update the topic with my solution.

Please do update if you come up with a solution. It will help others.


I have still been unable to solve this.

I attempted to create the new taxonomies and permalinks as explained in the pull request content, however they weren’t recognized at all, even when adding that data to the frontmatter of every post. Hugo still seems to regard the directory as priority for URL generation.

HOWEVER. In the docs at: https://gohugo.io/content-management/urls/#permalinks under “Permalinks configuration example” It says:

Only the content under post/ will have the new URL structure. For example, the file content/post/sample-entry.md with date: 2017-02-27T19:20:00-05:00 in its front matter will render to public/2017/02/sample-entry/index.html at build time and therefore be reachable at https://example.com/2017/02/sample-entry/ .

This is not my experience. With that example the content ends up at https://example.com/posts/2017/02/sample-entry/. Note the “posts/” addition.

The result that the documentation gives is exactly what I want. What hugo actually does is not.

So at this point I’m assuming that the documentation is incorrect and that there may be no way to do this and still have my content under the content/posts/ directory locally.

To explain what I want again (for anyone that doesn’t want to scroll up).

I have content at content/posts/sample-entry.md with category: diatribe" and a date of February 1st, 2017. I need this to be generated as:https://example.com/diatribe/2017/02/01/sample-entry.md`

No matter what I seem to do, I end up with /posts/ in my generated permalink.

If I sort all my posts in to /content/category/ and add over 50+ “permalink: category: /:section/:year/:month/:day/:filename/” with "uglyurls: true"in my config… then it works. However it’s a total mess in both my config file and for local organization.

(However, “uglyurls: true” breaks other parts of my site… Tags and Categories are rendered without index.html)

My site is active and live using Jekyll currently, and it’s very important that my permalinks stay the same for the content currently online.

A desperation bump.

Let’s see your project, maybe something can be done.

I’m sorry, but it is huge and private.

You can assume a default jekyll setup in regards to how paths and files are generated.

I don’t use Jekyll. Anyhow, you can set the URL per piece of content. Good luck! :slight_smile:

1 Like

Setting per post permalinks, or projectwide does not seem to work as I outlined above.

I can put together a small project to demonstrate the issue.

Go for it! I may not have an answer for your pattern, but I can troubleshoot general permalink wonkiness. :slight_smile:

Actually… using per-post aliases seems to work. I just need to write a script to add this to each post I think?

I will report back as I progress with this. I need to investigate a few other things.

Thank you for the idea maiki.

Cool! Just make sure you are reading https://gohugo.io/content-management/urls/#override-urls-with-front-matter. Aliases are slightly different, and I don’t think they fix your particular problem (with Disqus, for instance).

Ok, so what needs to be done to convert a default Jekyll 3.x site’s permalinks is:

  • Get the date from the file name.
  • Get the date from the yaml
  • Get the post name
  • Get the category name

Now add a “url: category/year/month/day/post-name.html” to the yaml

Here’s a very simple ruby script that does this. (No error checking). Pass it a directory of jekyll posts and it will add the "url: " key to the yaml in the default jekyll format.

So “ruby script.rb /path/to/posts/”

Do this on a backup! Never process files live!

I’m not a ruby programmer, I just felt like giving ruby a try today.

dir = ARGV[0]

Dir.foreach(dir) do |filename|
  next if filename == '.' or filename == '..' or (File.extname(filename) != ".md" and File.extname(filename) != ".markdown")

  f = File.open(filename, "r")
  year, month, day, post_name = File.basename(filename, ".*").match(/(\d*)-(\d*)-(\d*)-(.*)/).captures
  categories = ""
  new_file = ""
  File.open(filename, "r") do |f|  
    f.each_line { |line|
        if line =~ /^date:/
          if match = line.match(/(\d*)-(\d*)-(\d*)_/)
            year, month, day = match.captures
        if line =~ /^categories:/
          if match = line.match(/categories: (.*)/)
            categories = match.captures[0]
            new_file << "url: /#{categories}/#{year}/#{month}/#{day}/#{post_name}.html\n"
        new_file << line
  File.open(filename, 'w') do |f|
    f.write new_file