# Programmatically output pages from collection

**URL:** <https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031>\
**Category:** Help\
**Created:** [June 29, 2025, 2:24pm UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031 "2025-06-29T14:24:03Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![marmalamuc](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/marmalamuc/32/2149_2.png) [@marmalamuc](https://talk.jekyllrb.com/u/marmalamuc)\
**Post date:** [June 29, 2025, 2:24pm UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/1 "2025-06-29T14:24:03Z")

</div>

# Context

I have a local jekyll instance to manage my poetry, instead of dealing with a WYSIWYG editor. The poems are technically a separate jekyll project that I symlink to other jekyll projects (a submission manager, a personal website, [my first book](https://thegreatpermission.com)). I specify `_poems` as a Collection in each config file.

# Goal

I’m trying to specify pages from the `_poems` collection to access in a new page. But I can’t figure out how to get jekyll to access the collection programmatically. I can hardcode the paths with an `assign` + `for` loop, but this is tedious & error-prone.

# Details

I want to specify the file names from the `_poems` collection so that I can loop through them in a file like this:

```html
---
author: "marmalamuc"
title: "Submission example"
date: 2025-06-29
layout: default
permalink: example.html
poems:
  - poem1.html
  - poem2.html
  - poem3.html
---
<p>{% include contactInfo.md %}</p>

<p id="journal">{{ page.title }}<br>
{{ page.date | date: "%d %b %Y" }}</p>

<h2>Contents</h2>
<ul>
  {% for item in page.poems %}
  <li><a href="#poem{% increment counter1 %}">{{item.title}}</a></li>
  {% endfor %}
</ul>

{% for item in page.poems %}
  <div class="page-break" id="poem{% increment counter2 %}">
    <h3>{{ item.title }}</h3>
    {% if item.epigraph %}<p class="epigraph">{{item.epigraph}}</p>{% endif %}
    {{ item.content }}
    {% if item.dedication %}<p class="dedication">{{item.dedication}}</p>{% endif %}
  </div>
{% endfor %}

```

But I can’t figure out how to get jekyll to access the poems. The output is always blank (though it recognizes the correct number of items in the `ul` & page breaks). I’ve tried all kinds of things with `assign`, `capture`, `cycle`, but can’t get it to work if I specify the files as a group. For example, this (& several variations) does not work:

```html
{% for poem in page.poems %}
  {% assign p = site.poems | where: "permalink", "{{poem}}" %}
  <div class="page-break" id="poem{% increment var %}">
    <h3>{{ p.title }}</h3>
    {% if p.epigraph %}<p class="epigraph">{{p.epigraph}}</p>{% endif %}
    {{ p.content }}
    {% if p.dedication %}<p class="dedication">{{p.dedication}}</p>{% endif %}
  </div>
{% endfor %}

```

Everything does work if I hardcode a variable for each file (my current approach), or based on a frontmatter property in the poems, then loop through to grab the title & content; i.e.:

- `{% assign p1 = site.poems | where: "permalink", "poem1.html" %}`
- `{% assign ode = site.poems | where: "series", "ode" %}`

But the former is the tedious approach I’m trying to get away from, and the latter is not useful for creating submissions.

This is so simple in theory, but I’ve been banging my head against a wall for months trying to get it right.

Any ideas?

---

<div class="post-metadata">

**Author:** ![chuckhoupt](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/chuckhoupt/32/523_2.png) [@chuckhoupt](https://talk.jekyllrb.com/u/chuckhoupt)\
**Post date:** [June 29, 2025, 7:55pm UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/2 "2025-06-29T19:55:22Z")

</div>

One problem is the quotes and liquid-braces around `"{{poem}}"` in the `where` filter. That filters on the literal string “{{poem}}”, not on the value of the poem variable.

Mismatch: `where: "permalink", "{{poem}}"`  
Correct: `where: "permalink", poem`

---

<div class="post-metadata">

**Author:** ![marmalamuc](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/marmalamuc/32/2149_2.png) [@marmalamuc](https://talk.jekyllrb.com/u/marmalamuc)\
**Post date:** [June 30, 2025, 8:33am UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/3 "2025-06-30T08:33:32Z")

</div>

Thanks for taking a look! I had tried it without the brackets but still in quotes, but not as you suggested. Unfortunately the result is the same

---

<div class="post-metadata">

**Author:** ![chuckhoupt](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/chuckhoupt/32/523_2.png) [@chuckhoupt](https://talk.jekyllrb.com/u/chuckhoupt)\
**Post date:** [July 1, 2025, 1:16am UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/4 "2025-07-01T01:16:23Z")

</div>

The are a couple possibilities. One issue may be that page URLs/permalinks would typically start with a slash (e.g. `/poem1.html`), so the `page.poems` list items wouldn’t match the permalinks because they have no slash.

I think the best first debugging step is to see exactly what data is in `site.poems`. The [Liquid `inspect` filter](https://jekyllrb.com/docs/liquid/filters/#inspect) will output all an objects fields, so you can see exactly what you can filter. For example, to see the first poem, put this on the page (the `<pre>` is for readability):

```auto
<pre>{{ site.poems[0] | inspect }}</pre>

```

That should output something like this (made-up data):

```auto
{
  "url": "/poem1.html",
  "name": "poem1.markdown",
  "path": "_poems/poem1.markdown",
  "permalink": "/poem1.html",
  "title": "....",
  .... 

```

Now you can adjust the `where` filter and `page.poems` list to match the `permalink` or other fields.

---

<div class="post-metadata">

**Author:** ![marmalamuc](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/marmalamuc/32/2149_2.png) [@marmalamuc](https://talk.jekyllrb.com/u/marmalamuc)\
**Post date:** [July 1, 2025, 2:26pm UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/5 "2025-07-01T14:26:53Z")

</div>

Wow, I didn’t know about the `inspect` filter. That’s so useful.

I’m slightly more confused, because inspect is outputting all the yaml key:value pairs for the items I specify, so it’s definitely accessing the collection.

I’ll keep experimenting, and hopefully I’ll find the right syntax. Thanks!

---

<div class="post-metadata">

**Author:** ![chuckhoupt](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/chuckhoupt/32/523_2.png) [@chuckhoupt](https://talk.jekyllrb.com/u/chuckhoupt)\
**Post date:** [July 1, 2025, 3:38pm UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/6 "2025-07-01T15:38:05Z")

</div>

> [@marmalamuc](#):
>
> `{% assign p = site.poems | where: "permalink", "{{poem}}" %}`

Another issue here is that the resulting `p` is a filtered list, not an individual poem, so references like `p.title` will return nothing. You could explicitly dereference the list’s first item (`p[0].title`), but I think a cleaner way is to use the `first` filter to get the first (and presumably only) item from the list:

```auto
{% assign p = site.poems | where: "permalink", poem | first %}

```

After that `p.title` should work (use `p | inspect` if it doesn’t).

---

<div class="post-metadata">

**Author:** ![marmalamuc](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.jekyllrb.com/marmalamuc/32/2149_2.png) [@marmalamuc](https://talk.jekyllrb.com/u/marmalamuc)\
**Post date:** [July 2, 2025, 7:31am UTC](https://talk.jekyllrb.com/t/programmatically-output-pages-from-collection/10031/7 "2025-07-02T07:31:00Z")

</div>

Ah ha! The `first` filter was the solution for me.

I’m still a little confused because this solution looks the same to me as what I’d been doing—creating a variable for each poem: `{% assign p1 = site.poems | where: "permalink", "poem1.html" %}`

For posterity, here’s the setup I use to loop through items from a collection instead of hardcoding individual items:

```html
---
author: "marmalamuc"
title: "Submission example"
date: 2025-06-29
layout: default
permalink: example.html
poems:
  - poem1.html
  - poem2.html
  - poem3.html
---
<h2>Contents</h2>
<ul>
  {% for poem in page.poems %}
    {% assign p = site.poems | where: "permalink", poem | first %}
    <li><a href="#poem{% increment counter1 %}">{{item.title}}</a></li>
  {% endfor %}
</ul>

{% for poem in page.poems %}
  {% assign p = site.poems | where: "permalink", poem | first %}
  <div class="page-break" id="poem{% increment counter2 %}">
    <h3>{{ item.title }}</h3>
    {% if item.epigraph %}<p class="epigraph">{{item.epigraph}}</p>{% endif %}
    {{ item.content }}
    {% if item.dedication %}<p class="dedication">{{item.dedication}}</p>{% endif %}
  </div>
{% endfor %}

```

Grateful for your time, @chuckhoupt!
