Loop through ALL pages of the website

I want to create a loop that displays any of the last pages modified in my websites. Unfortunately, I cannot find a way to loop through collections and posts, too.

{% assign all = site.pages | sort: 'updated' | reverse | limit: 5 %}
<ul>
  {% for page in all %}
    <li>{{ page.updated }} - {{ page.title }}</li>
  {% endfor %}
</ul>

This loop gives me only the pages, not posts or collections.

Is there any way I can get all of the pages, so all of the files ending in .html or .md?

I just did a little test with pages and posts, which worked just fine. I assume you could also combine categories as well. Make sure you think through the logic very carefully with this approach. Pages, posts, and categories may have their own unique YAML front matter, so be sure to think about the display logic.

For example, If all your posts contain front matter with, say, featuredImage, but pages and categories do not have that, then you may have to write some custom logic before displaying content from each type. Hopefully, that makes sense :slight_smile:

To get all the pages, use this code:

{% assign pages = site.pages %}

However, I only like to get pages that have a title associated with them, so here’s a light modification if that is important to you:

{% assign pages = site.pages | where_exp: "item", "item.title" %}

Next, you will want all your posts, so add the following line:

{% assign posts = site.posts %}

Note that you rarely have to check for a title in posts because it is a required field, and if you do not add it to the front matter, the title is derived from the filename.

Finally, combine the arrays using the Liquid concat filter with the following code:

{% assign pagesAndPosts = pages | concat: posts %}

Here is a little code snippet that will traverse the new pagesAndPosts array and display the title for each item:

{% for pageAndPost in pagesAndPosts %}
    title: {{pageAndPost.title}}
{% endfor %}

As I mentioned earlier in this response, I was not able to test with categories. Still, I assume if you want to build a pagesPostsAndCategories array, it would look like the following code:

{% assign pagesPostsAndCategories = pages | concat: posts | concat: categories %}
1 Like

Oh yeah! Thanks a lot! The concat filter is the missing key I was looking for. Nevertheless, if you visit this test page (source code of the page), you notice that posts that to not have an explicit title declaration do not appear to have a title… this is odd.

I took a look at that code page and did not see all the arrays you are trying to combine on that page. I do not have time to go through your whole setup, so here I will provide you with the working code I developed for your solution. The following does work, at least on Jekyll 4.2.1:

## All pages
{% assign pages = site.pages | where_exp: "item", "item.title" %}
{% for page in pages %}
    title: {{page.title}}
{% endfor %}

## All posts
{% assign posts = site.posts %}
{% for posts in posts %}
    title: {{posts.title}}
{% endfor %}

## All pages and posts
{% assign pagesAndPosts = pages | concat: posts %}
{% for pageAndPost in pagesAndPosts %}
    title: {{pageAndPost.title}}
{% endfor %}

here my working. List 5 random posts and pages widget

{% assign all_content = site.posts | concat: site.pages %}
      {% assign sorted_content = all_content | sort: 'date' | reverse %}
      {% assign shuffled_content = all_content | sample: all_content.size | where_exp: "item", "item.title" %}
      <ul>
        {% for item in shuffled_content limit:5 %}
          {% if item.url %}
            {% assign url = item.url | prepend: site.baseurl %}
            <li><a href="{{ url }}">{{ item.title }}</a></li>
          {% endif %}
        {% endfor %}
      </ul>