Group by Category

Organize content into groups using Bengal's group_by filter

2 min read 362 words

Display content organized by category, tag, or any frontmatter field.

The Pattern

{% let by_category = site.pages
  |> where('section', 'docs')
  |> group_by('category') %}

{% for category, pages in by_category.items() |> sort %}
<section>
  <h2>{{ category | title }}</h2>
  <ul>
  {% for page in pages |> sort_by('weight') %}
    <li><a href="{{ page.href }}">{{ page.title }}</a></li>
  {% end %}
  </ul>
</section>
{% end %}

What's Happening

Step Purpose
group_by('category') Creates a dict:{category: [pages]}
.items() Iterate key-value pairs
| sort Alphabetize categories
sort_by('weight') Order pages within each category

Variations

{# Group blog posts by publication year #}
{% let posts = site.pages |> where('section', 'blog') |> sort_by('date', reverse=true) %}

{% let current_year = none %}
{% for post in posts %}
  {% let post_year = post.date.year %}
  {% if post_year != current_year %}
    {% let current_year = post_year %}
    <h2>{{ post_year }}</h2>
  {% end %}
  <li><a href="{{ post.href }}">{{ post.title }}</a></li>
{% end %}
{# Show all tags with their post counts #}
{% for tag, data in site.taxonomies.tags.items() |> sort %}
<div class="tag">
  <a href="{{ data.href }}">{{ tag }}</a>
  <span class="count">{{ data.pages | length }}</span>
</div>
{% end %}
{# Group by category, then by author #}
{% let by_category = site.pages |> group_by('category') %}

{% for category, cat_pages in by_category.items() %}
  <h2>{{ category }}</h2>

  {% let by_author = cat_pages |> group_by('author') %}
  {% for author, author_pages in by_author.items() %}
    <h3>{{ author }}</h3>
    {% for page in author_pages %}
      <li>{{ page.title }}</li>
    {% end %}
  {% end %}
{% end %}

Handle Missing Values

Pages without the grouped field go into aNonegroup:

{% let by_category = pages |> group_by('category') %}

{% for category, pages in by_category.items() %}
  {% if category %}
    <h2>{{ category }}</h2>
  {% else %}
    <h2>Uncategorized</h2>
  {% end %}
  {# ... #}
{% end %}

Seealso