Creating custom permalinks for each post category

Hi Forum, what I what to achieve is this. Say I have two types of categories, journals and essays.

I want essays to have the following permalink structure:

permalink: essay/:title

And journals to have the following permalink structure:

permalink: journal/:year/:month/:day/:title

Now, the reason behind this is because I want essays to have a shorter link so that they can be easily accessible through link like http://www.example.com/essays/title and journals to have a link structure that emphasizes on when they where created: http://www.example.com/journals/2017/03/07/title.

I would like to configure this in the _config.yml file, as apposed to writing the permalink setting in each of the post front-matter

My solution - Collections

Currently, I am able to solve the permalink problem with collections since you can explicitly define the permalink structure for each collection. What I did is create two new collections: journals and essays.

collections:
  essays:
    permalink: essay/:title
  journals:
    permalink: journal/:year/:month/:day/:title

However, the problem with collections that I have, is that they are mainly meant for non-post based content. Although they work as text-based content, I found some limitations. For example, site.related_posts only accounts for posts only. Many Jekyll plugins, jekyll-feed for example, relies mostly on posts and not collections to generate RSS feeds. So basically, I’m using collections for text-based stuff, which imposes some limits on the flexibility.

If there is a way to treat collections as posts, then that would probably solve my problem. But otherwise, I think the best way to go about this, is to define the permalink for each post category.

You’re on to the right idea building them as collections, but as you noted there are limitations.

I think what you can do is keep them as posts and group journals and essays together like this:

_posts
  \essay
    yyyy-mm-dd-your-essay-title.md
    yyyy-mm-dd-another-essay-title.md
    ...
  \journals
    yyyy-mm-dd-your-journal-title.md
    yyyy-mm-dd-another-journal-title.md
    ...

Then using front matter defaults in your _config.yml file you can target /essay and /journals and assign different permalink formats.

defaults:
  # Journals
  - scope:
      path: "_posts/journals"
      type: posts
    values:
      permalink: journal/:year/:month/:day/:title
  # Essay
  - scope:
      path: "_posts/essay"
      type: posts
    values:
      permalink: essay/:title

Which on build would give you what you want:

_site
\essay\your-essay-title.html
\essay\another-essay-title.html
\journal\yyyy\mm\dd\your-journal-title.html
\journal\yyyy\mm-\dd\another-journal-title.html

Hope this helps!

1 Like

This is great, thank you! There is one problem however. While the defaults: worked and both journals and essays now have the permalinks that I want, the .md files don’t get assigned to a category based on the directory name in which they are located in.

For example, when I apply the file structure that you suggested:

_posts
  \essays
    yyyy-mm-dd-your-essay-title.md
    yyyy-mm-dd-another-essay-title.md
    ...
  \journals
    yyyy-mm-dd-your-journal-title.md
    yyyy-mm-dd-another-journal-title.md
    ...

The essays are not present in site.categories.essays variable, nor are the journals in the site.categories.journals variable.

That used to work but I feel like something changed with Jekyll. Just assign a category using front matter defaults. It works for anything you’d put in a post’s front matter, not just permalink like in my example above.

defaults:
  # Journals
  - scope:
      path: "_posts/journals"
      type: posts
    values:
      permalink: journal/:year/:month/:day/:title
      category: journals
      foo: bar
  # Essay
  - scope:
      path: "_posts/essay"
      type: posts
    values:
      permalink: essay/:title
      category: essays
      whatever: [you, want]
      comments: true
      image: filename.jpg
3 Likes

I was just about to try this out and then I saw you post it! :grinning: It worked perfectly.

I appreciate your help!

This saved me a lot of time, thanks!