Why Use Centralized YAML for Related Posts?
Previously, we used series
or pillar
fields in post front matter. While effective, managing related content through front matter can get messy as your site grows. A centralized YAML file provides:
- Cleaner control over relationships
- Faster content updates without editing individual posts
- Support for non-linear or manual groupings
Step 1: Create a Data File for Related Posts
Create a file _data/related.yml
with structure like:
template-performance:
title: "Template Optimization Series"
posts:
- /jekyll/template-basics/
- /jekyll/layout-optimizations/
- /jekyll/template-performance/
- /jekyll/minification/
jekyll-site-structure:
title: "Jekyll Site Structure Guide"
posts:
- /jekyll/navigation-overview/
- /jekyll/building-sidebar/
- /jekyll/smart-related-posts/
- /jekyll/yaml-based-relationships/
Each group contains a title and a list of post URLs. This gives you full editorial control.
Step 2: Connect the Current Page to Its Group
In your post front matter, add a key to associate with a group in the YAML file:
---
title: "Jekyll Template Performance Tips"
category: jekyll
related_group: template-performance
---
Step 3: Render Related Posts from Data File
In your layout or include file, add the following logic:
{% assign group_key = page.related_group %}
{% assign group_data = site.data.related[group_key] %}
{% if group_data %}
<div class="related-posts">
<h3>More in: {{ group_data.title }}</h3>
<ul>
{% for url in group_data.posts %}
{% assign post = site.posts | where: "url", url | first %}
{% if post and post.url != page.url %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
This system checks the group for the current post, loads its title, and loops through all posts in that group, excluding the current one.
Step 4: Add a Fallback if No Group Found
To avoid empty output, consider adding a fallback using category or tag match:
{% unless group_data %}
<h3>Related Articles in {{ page.category | capitalize }}</h3>
<ul>
{% assign related = site.posts | where: "category", page.category | where_exp: "p", "p.url != page.url" | limit: 3 %}
{% for post in related %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
{% endunless %}
Advantages of the YAML-Based Approach
- Manual curation without editing post files
- Custom titles for related sections
- Cross-category linking is easy
- Better visibility for thematic or campaign content
Example Use Case: Campaign-Specific Guides
Imagine you're running a content campaign called “Launch Your Jekyll Site in a Week”. Instead of tagging or creating a category, just add a group like:
jekyll-launch-week:
title: "Launch Your Jekyll Site in a Week"
posts:
- /jekyll/setup-github-pages/
- /jekyll/choose-a-theme/
- /jekyll/write-first-post/
- /jekyll/push-live/
Now every article in that series gets meaningful related content, even if they span different categories or tags.
Tips for Maintaining Your Related YAML File
- Use descriptive keys (e.g.
launch-week
,performance-tips
) - Keep URLs updated — use relative URLs for consistency
- Use a validator or syntax checker for your YAML if working at scale
Bonus: Display Group Navigation
You can also display the current group’s full list as a navigation menu for multi-part articles:
<nav class="related-nav">
<h4>{{ group_data.title }}</h4>
<ol>
{% for url in group_data.posts %}
{% assign post = site.posts | where: "url", url | first %}
<li{% if post.url == page.url %} class="active"{% endif %}>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ol>
</nav>
Conclusion
By storing related post relationships in a YAML file, you unlock a structured, scalable, and highly flexible system. You can control related posts globally without modifying dozens of Markdown files, and the result is a much more coherent reading experience for your users.
In the next article, we’ll explore how to make this system multilingual by combining _data/related.yml
with _data/i18n
and language-aware layouts in Jekyll.