context-aware related posts in jekyll using liquid

Why Contextual Related Posts Improve Engagement Most "Related Posts" systems simply match by tags or categories. While this works in many cases, it can feel too broad. A more intelligent approach is to show posts that are related based on the user's context or the post’s core theme. This increases reader retention and keeps your content experience focused. We’ll use Jekyll’s powerful Liquid syntax to achieve context-sensitive recommendations. Core Idea Behind Context-Aware Related Posts Instead of relying solely on tags or categories, you can: Define a primary topic for each post Group related posts by series , pillar , or type Set up fallback logic if no strong match exists This way, you can recommend: Other parts of a tutorial series Posts targeting the same user intent Posts with the same use case (e.g. Jekyll for documentation) Step-by-Step: Smarter Related Posts Step 1: Define Contextual Fields In your post front matter, add...

Smarter Related Posts with JSON + JavaScript

For larger Jekyll sites or when you want fuzzy matching (e.g., shared keywords in titles or content), Liquid has limitations. This is where a JavaScript-based related post system becomes powerful. It loads a pre-built posts.json file and runs similarity matching in the browser, offering great flexibility without plugins or server-side logic.

1. Export Your Posts into a JSON File

Create a file like related.json or all-posts.json inside your _site directory using a custom layout that Jekyll will render. Here's how:


# _pages/posts.json
---
layout: null
permalink: /posts.json
---

[
  {% for post in site.posts %}
    {
      "title": {{ post.title | jsonify }},
      "url": "{{ post.url }}",
      "tags": {{ post.tags | jsonify }},
      "categories": {{ post.categories | jsonify }},
      "excerpt": {{ post.excerpt | strip_html | truncate: 150 | jsonify }},
      "content": {{ post.content | strip_html | jsonify }}
    }{% unless forloop.last %},{% endunless %}
  {% endfor %}
]

Save this with front matter so Jekyll renders it. After site build, it will be accessible at /posts.json.

2. Load JSON and Compute Matches on Client Side

In your post layout, include a small JavaScript snippet that fetches the JSON, then compares tags or content similarity with the current post.

<script>
document.addEventListener("DOMContentLoaded", function () {
  const currentTitle = document.querySelector("meta[property='og:title']")?.content || document.title;
  const currentTags = JSON.parse(document.querySelector("meta[name='post-tags']")?.content || "[]");

  fetch("/posts.json")
    .then((res) => res.json())
    .then((posts) => {
      const related = posts
        .filter(p => p.title !== currentTitle)
        .map(p => {
          let score = 0;
          currentTags.forEach(tag => {
            if (p.tags.includes(tag)) score += 1;
          });
          if (p.title.includes(currentTitle.split(" ")[0])) score += 1;
          return { ...p, score };
        })
        .filter(p => p.score > 0)
        .sort((a, b) => b.score - a.score)
        .slice(0, 5);

      const container = document.getElementById("related-posts");
      if (container && related.length) {
        container.innerHTML = `
          <h3>Related Posts</h3>
          <ul>
            ${related.map(post => `<li><a href="${post.url}">${post.title}</a></li>`).join("")}
          </ul>
        `;
      }
    });
});
</script>

And in your HTML, define the container:

<div id="related-posts"></div>

3. Embed Tags as Meta Tags for Runtime Access

Add this inside your HTML <head> section of the post layout:

{% raw %}


{% endraw %}

Advantages of the JSON + JS Method

  • Scalable: No Liquid performance hit.
  • Smarter logic: You can implement fuzzy, weight-based matching.
  • Realtime: Easy to update without rebuilding entire site.
  • Flexible rendering: You can add thumbnails, excerpts, or even dynamic filters.

Optional: Preprocess Related Posts Offline

For advanced control, you can generate related post relationships during build time using Python, Node.js, or Go. These scripts analyze your markdown files, compute similarity, and write them into a JSON like this:


{
  "/post-a/": ["/post-b/", "/post-c/", "/post-d/"],
  "/post-x/": ["/post-y/", "/post-z/"]
}

You can then load this in JavaScript, match against location.pathname, and render the list with pure frontend code.

Conclusion

By combining Jekyll's static generation with a lightweight client-side JS engine, you get the best of both worlds: fast, scalable related content without needing plugins or third-party APIs. This approach gives full control over logic, weight scoring, and styling—all while staying within the GitHub Pages framework.

In the next tutorial, we’ll explore integrating this related-posts engine with Lunr.js or FlexSearch so it can work together with site search, building an intelligent, full-text-aware content discovery system for static blogs.


Archives / All Content


© GlowAdHive🕒😀😃😀 . All rights reserved.