Combining Tags and Categories for Smart Index Navigation

Why Merge Tags and Categories in Jekyll Most Jekyll sites separate tags and categories into distinct navigation paths. Categories are often shown in sidebars or menus, while tags live in post metadata or isolated tag pages. This division creates friction for users who want to browse content naturally based on relevance or context. By combining both systems in one smart index, we allow visitors to explore both hierarchical and associative relationships between content items. This results in better usability, discoverability, and even SEO improvements due to internal link clustering. Use Case: A Developer Knowledge Base Let’s say we’re building a knowledge base for developers using Jekyll collections. Each resource item belongs to a category like “Performance” or “Theming,” and also has tags such as “includes,” “scss,” or “responsive.” Our goal is to create an index that looks like this: Performance (category) includes (tag) Optimizing I...

Structuring Your Jekyll Site with Custom Collections

Why Jekyll Collections Are Essential for Structured Content

As your static site grows beyond simple blog posts and pages, you’ll eventually need more structure. Maybe you’re building a documentation portal, a changelog, or a showcase of portfolio projects. That’s where Jekyll collections come in.

Collections allow you to define and group custom content types—like tutorials, features, case studies, or FAQs—that behave similarly to posts, but with greater control over how they’re organized, rendered, and accessed.

What Are Jekyll Collections?

A collection is a group of related documents stored in its own folder (prefixed with an underscore, like _tutorials) and configured in _config.yml. Unlike posts, collections don’t require date-based filenames and can have arbitrary naming, front matter, and permalink structures.

This makes them ideal for organizing content that:

  • Isn’t blog-like in nature (no date relevance)
  • Needs its own layout, filters, and structure
  • Should be queryable across templates using Liquid

Setting Up a Basic Collection

Let’s say you want to create a tutorial library. Start by defining it in your _config.yml:

collections:
  tutorials:
    output: true
    permalink: /tutorials/:path/

This tells Jekyll:

  • There’s a new collection called tutorials
  • Its files should be rendered as pages (output: true)
  • Its URLs will follow the pattern /tutorials/filename/

Then create the folder _tutorials in your root directory and add your content:

_tutorials/
  getting-started.md
  advanced-tricks.md

Each file should have front matter:

---
title: Getting Started
layout: tutorial
difficulty: beginner
---

You now have a functioning tutorial collection with custom metadata!

Rendering a Collection in Your Site

To list the tutorials on a dedicated page, create tutorials.html:

---
layout: default
title: Tutorials
---

All Tutorials

    {% raw %}{% for tutorial in site.tutorials %} <li><a href="{{ tutorial.url }}">{{ tutorial.title }} ({{ tutorial.difficulty }})</a></li> {% endfor %}{% endraw %}

This uses the site.tutorials collection array and loops through each item. You can use any front matter property (like difficulty) for filtering or display.

Use Case: Creating a Team Directory

Suppose your site has a growing number of contributors or staff. Rather than hardcoding them into a single HTML file, you can build a _team collection.

In _config.yml:

collections:
  team:
    output: true
    permalink: /team/:name/

Inside _team/:

_team/
  alice-smith.md
  bob-lee.md
---
name: Alice Smith
position: Head of Design
photo: /assets/img/alice.jpg
layout: team-member
---

Then you can create a team listing page:

{% raw %}{% for person in site.team %}
  <div class="team-card">
    <img src="{{ person.photo }}" alt="{{ person.name }}" />
    <h3>{{ person.name }}</h3>
    <p>{{ person.position }}</p>
  </div>
{% endfor %}{% endraw %}

This approach is scalable, easier to maintain, and allows linking to individual team member pages.

Filtering, Sorting, and Grouping

You can do much more with collections by using Liquid filters:

Sorting Tutorials by Difficulty

{% raw %}{% assign sorted_tuts = site.tutorials | sort: "difficulty" %}
{% for tutorial in sorted_tuts %}
  <p>{{ tutorial.title }} - {{ tutorial.difficulty }}</p>
{% endfor %}{% endraw %}

Filtering by Tag

{% raw %}{% for tutorial in site.tutorials %}
  {% if tutorial.tags contains "liquid" %}
    <li>{{ tutorial.title }}</li>
  {% endif %}
{% endfor %}{% endraw %}

This allows you to build dynamic interfaces that group or filter custom content types.

Advanced Structure: Nested Collections with Data Files

Collections can be enriched further by combining them with data files. For example, imagine each tutorial links to downloadable assets listed in _data/assets.yml:

getting-started:
  - name: "Starter Code"
    url: "/downloads/starter.zip"
advanced-tricks:
  - name: "Trick Scripts"
    url: "/downloads/scripts.zip"

Then in your tutorial.html layout:

{% raw %}{% assign files = site.data.assets[page.slug] %}
{% if files %}
  <h3>Downloads:</h3>
  <ul>
    {% for file in files %}
      <li><a href="{{ file.url }}">{{ file.name }}</a></li>
    {% endfor %}
  </ul>
{% endif %}{% endraw %}

Combining collections with external data gives you powerful flexibility for building interfaces that are content-driven but dynamic in structure.

Pagination with Collections

Pagination doesn’t work out-of-the-box for collections like it does for posts, but you can use the jekyll-paginate-v2 plugin (for non-GitHub Pages environments) or custom pagination logic for client-side rendering using JavaScript.

On GitHub Pages, use collection slicing in Liquid for basic pagination emulation:

{% raw %}{% assign tutorials = site.tutorials %}
{% for tutorial in tutorials offset:0 limit:5 %}
  <li>{{ tutorial.title }}</li>
{% endfor %}{% endraw %}

Best Practices When Using Collections

  • Always set output: true if you want individual pages to render
  • Use consistent front matter keys to simplify querying and filtering
  • Use permalink to control the output path format per collection
  • Combine with defaults to reduce boilerplate in each file
  • Document collection usage for your contributors

Real World: Managing a Developer Changelog

A software project on GitHub Pages uses a _changelog collection to track releases. Each entry includes:

---
version: 2.3.0
date: 2024-11-03
changes:
  - "Added user audit log"
  - "Improved caching performance"
layout: changelog
---

The changelog page loops through site.changelog and groups by major version. This structure is easier to maintain and automatically adds new entries as files are committed.


Archives / All Content


© AdTrailScope🕒😀😀😀 . All rights reserved.