A while ago I migrated my company website from NextJS to Jekyll, and so far I have no regrets: for a static website generator, Jekyll is pretty flexible and suits all my needs.
I did run into an issue though when I wanted to move my blog posts to a subdirectory of my website without sacrificing search rankings — Jekyll’s static nature definitely makes this a little tricky, but not impossible. I’ll tell you how I went about it in this post.
Last week I realized that the url to my blog was https://branie.it/blog/, but my actual posts resided in https://branie.it/:year:/:month:/:day:/name-of-a-blogpost.html
i.e. without the /blog
prefix — this discrepancy doesn’t hurt anyone, not even search rankings, but it annoyed me enough to want to do something about it.
The challenge: preserve SEO and avoid broken links
When you change the URL structure of your site, search engines might treat old links as broken, which could cause your search rankings to drop. Furthermore, any external links pointing to your old blog post URLs will no longer work.
I knew that if I wanted to restructure my blog while keeping my search rankings intact, I needed to set up proper redirects from the old URLs to the new ones, but how would I do that in a static website where I only have static content at my disposal, and unable to use .htacccess
and the like? Luckily, Jekyll makes it easy to handle this with a little customization.
Why existing options didn’t work for me
The goto solution for this situation seems to be the jekyll-redirect-from plugin, which would actually solve my exact problem. Blogpost over, right?
Alas, it wasn’t that easy, because I wasn’t fully on board with their approach: to create one or more redirects to a particular post, you need to add one or more aliases to the Front Matter of each individual page. But what I was looking for was a way to configure redirects in a central place like _config.yml
.
So, I figured “how hard could it be” and started working on my own solution — it turned out to be pretty straight-forward 😄
Rolling my own
Step 1: find out how the jekyll-redirect-from plugin solves the problem
We only have static content at our disposal, so how will we use it to create redirects? The answer I found in the source of the jekyll-redirect-from
plugin was to use a <meta http-equiv="refresh" ...
header with a 0
seconds timeout.
But that’s not a 301
or 302
redirect, which is what I would have used were I not using a static website. What does Google think of this? Well, apparently it treats meta refresh
with a timout of 0
seconds like a 301
redirect:
Instant
meta refresh
redirect: Triggers as soon as the page is loaded in a browser. Google Search interprets instantmeta refresh
redirects as permanent redirects.
Great! So I can use pure HTML to achieve the same 301
redirects I would have used, were I using a dynamic website 🎉
With this knowledge, I took the layout from jekyll-redirect-from
plugin, copied it to _layouts/redirector.html
and adapted it to my own liking:
Step 2: generating a yaml configuration containing all redirects
Ok, so we have a redirect layout, now we need to generate some pages for it. As I mentioned earlier I’m looking for a solution where I can define my redirects in _config.yml
, which is why I wrote the quick-and-dirty Python script below, which takes care of generating a redirector
config section, where all existing blogposts are mapped to their new location.
You just run it the first time you move your blogposts to a subdirectory, so existing url’s aren’t lost. New url’s don’t need a mapping, because they never existed in another place, so no need to update the config.
Simply run it with:
--path-to-posts
set to the absolute path to the_posts
directory of your Jekyll installation--target-url
set to the new relative base url for your blogposts
Which might look something like this:
redirector_config_generator.py \
--path-to-posts /local/path/to/jekyll/_posts \
--target-url /blog
And you’ll end up with an output like the snippet below, which you should copy to your _config.yml
.
redirector:
- from: /2024/12/19/some-blogpost-about-jekyll.html
to: /blog/2024/12/19/some-blogpost-about-jekyll.html
- from: ...
to: ...
...
Step 3: install the redirector plugin hook
And the final step is to generate static, instantmeta-refresh
redirect pages in the locations defined by the mapping we just added to _config.yml
in the previous step.
I wrote the Jekyll hook plugin below, that you simply copy to _plugins/redirector.rb
after which you’re all set!
Results
- No Broken Links: All the old blog URLs now redirect correctly to the new
/blog
paths. - SEO Retention: By setting up
301
redirects through the use ofmeta refresh
, I preserved the link equity and rankings for my old blog posts.
Conclusion
Migrating your Jekyll blog posts to a subdirectory doesn’t have to be complicated. With a little effort, and applying the steps layed out in this article, Jekyll makes it easy to implement clean redirects that keep your site’s structure organized without sacrificing SEO.