Creating custom permalinks for each post category


#1

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.


#2

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!


#4

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.


#5

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

#6

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

I appreciate your help!