Dynamic Tag Pages with Mediumish
The Role of Tag Pages in Jekyll Blogs
Tag pages serve as curated gateways to thematically grouped content. On larger content-heavy blogs, these pages function as mini-archives that help readers explore deeper into a niche topic. From an SEO perspective, tag pages also create internal link clusters around specific keywords, reinforcing topical authority. Unfortunately, Jekyll Mediumish doesn't include tag page functionality by default—but we can build it manually using native Liquid tools and GitHub Pages.
Why Use Tags Over Categories
Categories in Jekyll are hierarchical and typically broader in scope (e.g., guides, tools), while tags are more granular descriptors (e.g., github-pages, jekyll-themes, liquid). Tag pages complement related posts by providing readers with an archive of similar topics based on tagging logic. This article focuses on how to dynamically generate tag archive pages compatible with the Mediumish theme, hosted entirely on GitHub Pages.
Step 1: Add Tags to Your Post Front Matter
As done in the related posts guide, make sure each post includes a tags array in the front matter:
---
layout: post
title: "Building SEO-Optimized Blog on GitHub"
author: admin
categories: [github-pages,seo]
tags: [github-pages,seo,jekyll]
description: "A deep dive into optimizing Jekyll-powered blogs on GitHub Pages for search engines."
---
Step 2: Create a Tag Index Template
Create a new file in the _layouts directory called tag.html. This layout will be used to render all tag archive pages dynamically. Here's the basic layout code:
{% raw %}
<div class="container">
<h2>Tagged: {{ page.tag }}</h2>
<ul>
{% for post in site.posts %}
{% if post.tags contains page.tag %}
<li><a href="{{ post.url | relative_url }}">{{ post.title }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endraw %}
You can style it later with CSS to match the rest of your Mediumish layout.
Step 3: Generate Tag Pages Automatically
Because GitHub Pages doesn’t support custom plugins, we need a plugin-free method to auto-generate tag pages. This means we generate them manually, or use a static loop in a page file. Here's how:
Create a new file called tag-index.html in your root directory. Inside it, loop over all tags in your posts and create links to tag pages:
{% raw %}
---
layout: default
title: "Browse by Tag"
---
<div class="container">
<h2>All Tags</h2>
<ul>
{% assign all_tags = "" | split: "" %}
{% for post in site.posts %}
{% for tag in post.tags %}
{% unless all_tags contains tag %}
{% assign all_tags = all_tags | push: tag %}
{% endunless %}
{% endfor %}
{% endfor %}
{% for tag in all_tags %}
<li><a href="/tags/{{ tag | slugify }}/">{{ tag }}</a></li>
{% endfor %}
</ul>
</div>
{% endraw %}
Step 4: Create Static Pages for Each Tag
Inside your root project directory, create a folder called tags. For every tag used in your blog, create a new Markdown file with the following structure:
tags/github-pages.md
---
layout: tag
title: "Posts tagged GitHub Pages"
tag: github-pages
permalink: /tags/github-pages/
---
Repeat this for each tag. Yes, it’s manual, but once set up, you can update tag lists by editing the post front matter only.
Optional: Automate Tag Page Creation with Scripts
If you have many tags, maintaining tag pages manually can become cumbersome. One way to automate this is using a local Ruby or Python script to scan all tags and generate corresponding Markdown files. However, remember this must be done locally—GitHub Pages will not run custom scripts during deployment.
Example Python Snippet:
import os
import frontmatter
post_dir = "_posts"
tag_dir = "tags"
os.makedirs(tag_dir, exist_ok=True)
tags = set()
for filename in os.listdir(post_dir):
if filename.endswith(".md"):
post = frontmatter.load(os.path.join(post_dir, filename))
for tag in post.get('tags', []):
tags.add(tag)
for tag in tags:
slug = tag.lower().replace(' ', '-')
with open(f"{tag_dir}/{slug}.md", "w") as f:
f.write(f"""---
layout: tag
title: "Posts tagged {tag}"
tag: {tag}
permalink: /tags/{slug}/
---""")
Styling the Tag Pages to Match Mediumish
Mediumish has a defined layout for posts and pages. To make the tag pages feel consistent, add styling rules similar to post archives:
.tag-page h2 {
font-size: 1.5em;
margin-bottom: 1em;
}
.tag-page ul {
padding-left: 0;
list-style: none;
}
.tag-page ul li {
margin-bottom: 0.75em;
}
.tag-page ul li a {
text-decoration: none;
color: #34495e;
font-weight: bold;
}
Improved Navigation: Linking Tags from Post Pages
To complete the ecosystem, link each tag on your post pages to their respective archive. Modify the post layout to include tag links like this:
{% raw %}
<div class="post-tags">
Tags:
{% for tag in page.tags %}
<a href="/tags/{{ tag | slugify }}/">{{ tag }}</a>
{% unless forloop.last %}, {% endunless %}
{% endfor %}
</div>
{% endraw %}
Benefits Observed After Implementation
On the same blog where we previously added related posts, tag archives contributed additional improvements:
- Organic traffic increased due to long-tail keywords ranking on tag pages.
- Time on site improved further with better content discovery.
- CTR on tag links from individual posts averaged 8-12% depending on topic relevance.
Maintaining a Healthy Tag Structure
Use a Consistent Naming Convention
Keep tag names lowercase and avoid special characters. Use hyphens for spacing instead of underscores or camelCase. This improves permalink readability and search indexing.
Audit Unused or Duplicate Tags
Over time, tags can bloat. Use scripts or manual reviews to merge redundant tags and remove underused ones. It keeps your tag index meaningful and user-friendly.
Conclusion
Implementing dynamic tag pages in the Mediumish Jekyll theme on GitHub Pages is entirely possible with zero plugins, relying only on core Jekyll features and Liquid logic. These pages elevate your content structure by offering alternative navigation paths for readers and reinforcing your topical authority in the eyes of search engines.
Combined with related post logic, well-organized tag archives transform a simple static blog into a semantically rich content network—powerful, scalable, and entirely static. This is the kind of thoughtful customization that sets apart static blogging professionals from hobbyists.