# How to filter only top-level pages in category

**URL:** <https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858>\
**Category:** Help\
**Created:** [January 6, 2022, 10:15pm UTC](https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858 "2022-01-06T22:15:13Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlconlin](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/jlconlin/32/2845_2.png) [@jlconlin](https://talk.jekyllrb.com/u/jlconlin)\
**Post date:** [January 6, 2022, 10:15pm UTC](https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858/1 "2022-01-06T22:15:13Z")

</div>

I have a Jekyll category (`NDT`). In that category, I have several pages and many sub pages. On the main page for the category (`/NDT/index.md`), I want to provide links to all the pages, but none of the sub pages. I tried to do this:

```auto
<ul>
  {% for page in site.NDT %}
    {% if page.dir == 'NDT' %}
      <li><a href="{{ page.url }}">{{ page.title }}</a></li>
    {% endif %}
  {% endfor %}
</ul>

```

This didn’t work because the `page.dir` variable was blank/empty for all my pages.

**Thoughts on how I might be able to do this?** Note, I don’t want to have to add another bit of metadata to the pages if I can avoid it. If unavoidable, I will do that, but would rather not.

---

<div class="post-metadata">

**Author:** ![BillRaymond](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/billraymond/32/5963_2.png) [@BillRaymond](https://talk.jekyllrb.com/u/BillRaymond)\
**Post date:** [January 7, 2022, 1:52am UTC](https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858/2 "2022-01-07T01:52:00Z")

</div>

There are several ways you can do this, and I bet you could get fancy with URL filters, but here is the way I know how to do it 🙂

## Reference

Before I begin, you should learn the `assign` tag for creating variables. It is powerful and helps you avoid that nest for/if loop you created by using the `where` filter, as you will see in my answer below.

## My understanding of the question

You have a folder that I will just call `docs`. Under that folder there are a number of files and folders, like this:

```auto
/docs/RootDoc.md
/docs/index.md (or index.html)
/docs/subdocs/SubDoc.md

```

The RootDoc.md file looks something like this:

```auto
---
layout: default
title: Rootdoc
category: NDT
---
This is a page located at the root of the RootDoc folder...

```

The SubDoc folder looks something like this:

```auto
---
layout: page
title: Subdoc
category: NDT
---
This is a page located in the SubDocs folder, underneath RootDoc...

```

The index page should **only** display the list of pages where that index file resides.

## Option #1: Add more YML front matter (your least preferred option)

Of course, one way to solve this problem is to add some new YAML element(s) to filter the content more easily. I added a new YML front matter item called `subfolder` and set that to `true` or `false` in my simplistic example.

```auto
---
layout: page
title: Subdoc
category: NDT
subfolder: false
---
This is a page located in the SubDocs folder, underneath RootDoc...

```

With that code in place, I can then write code like this:

```auto
{% assign ndtPages = site.pages | where: "category", "NDT" | where: "subfolder", false %}
{% for ndtPage in ndtPages %}
    title: {{ ndtPage.title }}
{% endfor %} 

```

You mention that this method is not ideal because you have to edit many files. Search this site for `regex`, and you will see several recent posts that cover how to do that global replacement in a folder of files using Visual Studio Code.

## Option #2: Count the number of subfolders (proposed solution)

If you want to know where the document is located, you can get the `page.url`, and it will return something that looks like this:

```auto
/docs/rootdoc.html

```

You can use the Liquid string `split` filter to turn the URL into an array, breaking up the string using the slash (`/`). Since there are _2_ slashes in my example, the array will be a size of _3_.

Here is a document in a subfolder:

```auto
/docs/subdocs/subdoc.html

```

There are _3_ slashes in that example, so you get an array size of _4_.

Now, let’s use this knowledge to our advantage.

Here is the code I would write to only get a split URL string with an array size of 3 (or 2 slashes):

```auto
{% assign ndtPages = site.pages | where: "category", "NDT" %}
{% for ndtPage in ndtPages %}
    {% assign folderCount = ndtPage.url | split: '/' %}
    {% if folderCount.size == 3 %}
      Page title: {{ ndtPage.title }}
      Page folder location: {{ ndtPage.url }}
    {% endif %}
{% endfor %}

```

First, we use `assign` to create a collection of `pages` that contain a `category` of `NDT` in the YML front matter.

We then loop through all the pages, but before we do anything, we `assign` a variable to convert the URL to an array with each item split based on the `/`.

Now that we have the array, we will only act on the page if the new array has a value of _3_ (or two slashes `/`).

From there, we put whatever content we want on the page, such as displaying the page title and whatever else you want within the `if` statement.

## Considerations

I do not know how deep your folder structure goes, so display the `page.url` somewhere, count the slashes, and add +1.

Once you get the folder count size right, you will hard-code the folder count into your code. In my case, I have `{% if folderCount.size == 3 %}`, but yours might be 5 or 8, or whatever. You may also move around the structure of your site.

I recommend you decide how many levels your pages have and add those values to your `_config.yml` file. For example, you could add the following line anywhere:

```auto
# Folder structure+1 for what level of doc to display: 
rootDoc: 3
subDoc: 4

```

Then, you can replace:

```auto
{% if folderCount.size == 3 %}

```

With:  
{% if folderCount.size == site.rootDoc %}

With that consistency in place, if you move your pages around, all you need to do is change the `_config.yml` file, rather than the logic in all your index pages.

## Final note

I will be honest, I could not figure out why `split` output a 3 instead of a 2 because I rarely use it. Just in case my +1 logic does not work, use this sample code:

```auto
{% assign ndtPages = site.pages | where: "category", "NDT" %}
{% for ndtPage in ndtPages %}
    {% assign folderCount = ndtPage.url | split: '/' %}
    Array size: {{ folderCount.size }}
    title: {{ ndtPage.title }}
    folder: {{ ndtPage.url }}
{% endfor %}

```

That will display all pages with NDT and you can get the `Array size` number to find out the number to put into your `if` statement in the solution I provided earlier.

Hope this helps!

---

<div class="post-metadata">

**Author:** ![jlconlin](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/jlconlin/32/2845_2.png) [@jlconlin](https://talk.jekyllrb.com/u/jlconlin)\
**Post date:** [January 7, 2022, 5:38pm UTC](https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858/3 "2022-01-07T17:38:15Z")

</div>

Thanks @BillRaymond. The idea to look at the number of folders in the URL was a great and did the job. Now I don’t have to add extra metadata.

---

<div class="post-metadata">

**Author:** ![BillRaymond](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/billraymond/32/5963_2.png) [@BillRaymond](https://talk.jekyllrb.com/u/BillRaymond)\
**Post date:** [January 7, 2022, 6:00pm UTC](https://talk.jekyllrb.com/t/how-to-filter-only-top-level-pages-in-category/6858/4 "2022-01-07T18:00:37Z")

</div>

Great news! Glad this solution worked for you!
