Collection showing up empty

I’m trying to create an iTunes XML feed for a podcast where each podcast episode will be a post on a Ghost 2.0.2 blog with the tag episode. Public available url http://bcurious.heiberg.io/

I’ve created 4 posts 3 of which have the episode tag.

I’ve changed my routes.yaml config:

routes:

collections:
  /:
    permalink: /{slug}/
    template:
      - index
  /episodes/:
    permalink: /episodes/{slug}/
    rss: true
    filter: 'tag:episode'

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

I would expect http://bcurious.heiberg.io/episodes/ to list 3 episodes instead it’s just an empty page. Interestingly the title tag is bcurious (Page 1) which is curious?

I was just going to use a channel, but as I understand it channels don’t get rss feeds.

Furthermore I would expect http://bcurious.heiberg.io/rss/episodes/ to have an rss feed with 3 episodes but it 404’s.

Once above is fixed I need to modify the “template” for the rss feed. I don’t see any docs about how to do this though.

Hey!

The first collection doesn’t use a filter and will own all posts, that’s why your episodes collection is empty. The collections are defined in a hierarchy.

You have to use filter: 'tag:-episode' for the first collection to exclude these posts.

Let us know if it worked :slight_smile:

1 Like

Dang the docs did say that. I for some reasons forgot to think of index as a collection. In that case is there a way to create a rss feed for a channel?

It is my desire for the front page to include a list of both episodes and blog posts intermixed chronologically.

That being said the following config:

routes:

collections:
  /:
    permalink: /{slug}/
    filter: 'tag:-episode'
    template:
      - index
  /episodes/:
    permalink: /episodes/{slug}/
    filter: 'tag:episode'
    rss: true

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

Has caused the index page to be empty and the /episodes page to be empty?

I have just tested your routes.yaml example - works fine for me.

I have a guess. Is the episode tag the primary tag of the target posts (first position)?

@Kate I tested too and I have a couple of questions.

  1. Would this create some problems in the future? Instead of tag:-episode for first collection, I replaced the order. Seems fine for me. But I’m curios if something will go wrong at a certain step.
routes:

collections:
  /episodes/:
    permalink: /episodes/{slug}/
    rss: true
    filter: 'tag:episode'
  /:
    permalink: /{slug}/
    template:
      - index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/
  1. Is there a way to show both type of collections on homepage? I mean, I’m interested to see if there is a way to show both default posts and episodes in the default loop? Like @andheiberg said.

From the docs: “Posts can match the filters of multiple collections, when that happens the first collection with a match will take ownership of that post so it won’t appear under any other collections.”

If I understand correctly you can’t have a post in 2 collections.

  1. Is there a way to exclude the episode from tag taxonomy.

The link:
http://localhost:2369/episodes/ → valid
http://localhost:2369/tag/episode/ → still valid

Thanks

Interesting that we’re getting different results.

Yes it’s the first an only tag on the 3 posts. The fourth post has no tags.

Yeah it will. Pagination can break if you don’t explicitly use a filter. This is because the actual database query doesn’t use the filter and the Ghost logic has to manually filter them out. e.g. it can happen that the page limit is 10, but it only shows 7 posts and there is another page 2. That’s why we highly recommend using a filter for any collection :slight_smile: I hope that answers your question.

Is there a way to show both type of collections on homepage? I mean, I’m interested to see if there is a way to show both default posts and episodes in the default loop? Like @andheiberg said.

You could create a channel to display all posts? A channel is a view. A channel does not define the url of a post.

Is there a way to exclude the episode from tag taxonomy.

If you define data: tag.episode, the taxonomy will redirect to /episodes/.

1 Like

Valuable pieces of insight. I hoped that would lead me to the solution I desired. Sadly it doesn’t work.

routes:
  /:
    controller: channel

collections:
  /posts/:
    permalink: /posts/{slug}/
    filter: 'tag:post'
    data: tag.post
    rss: true
    template:
      - index
  /episodes/:
    permalink: /episodes/{slug}/
    filter: 'tag:episode'
    data: tag.episode
    rss: true
    template:
      - index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

Success / lists 4 posts - the channel works
Success /rss/ lists 4 posts - the rss feed is using the channel or simply just using all stories. Either way I’m happy with that.
Failure /episodes/ shows 0 posts
Failure /rss/episodes/ 404’s
Failure /posts/ 404’s - why is this behaving differently than the /episodes/ endpoint?

Aha turns out the rss endpoint is at /episodes/rss/ and it works as I would expect.

I still don’t know how to modify the rss template though?

/posts/rss/ is also 404’ing though :frowning:

Does this tag exist? :thinking:

Yes I added a post tag to the single post that’s supposed to not be in the itunes rss feed.

You can see it called “Random blog post” on http://bcurious.heiberg.io/. However, clicking on it leads to /404/ which is super weird.

Looks to be an issue with “post” being a reserved value? See how the tag has url /post-tag not /post. I tried editing it to /post and it refused and made a /post-tag-2.

36

Yes true, “post” is a reserved slug.

I changed the slug to postz which still didn’t work.

I then deleted the random post and made a new identical one and it now works. It’s pretty annoying for post to be a reserved slug though? Why is that?

But barring the glaring use of postz I’m reasonably happy.

How do I change the template for the rss feed though?

We can use the precedence rules for collections to get around post being a reserved tag. Simply remove the post tag and use the posts collection as a catch all:

routes:
  /:
    controller: channel

collections:
  /episodes/:
    permalink: /episodes/{slug}/
    filter: 'tag:episode'
    data: tag.episode
    rss: true
    template:
      - index
  /posts/:
    permalink: /posts/{slug}/
    rss: true
    template:
      - index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

Does give me:

Success / lists 4 posts
Success /rss/ lists 4 posts
Success /episodes/ lists 3 posts
Success /episodes/rss/ lists 3 posts
Success /posts/ lists 1 post
Failure /posts/rss/ lists 4 posts

Granted the /posts/rss somehow shows more stories than it should?! but I don’t really care about that.

Now my only issue is modifying the rss template.

Will try to reproduce asap.

Now my only issue is modifying the rss template.

Looks like this example is missing in our docs :thinking: You can disable rss for a collection and define a custom route.

This should work (use the template name you want to choose):

routes:
  /posts/rss/:
    template: posts-rss
    content_type: xml

collections:
  /posts/:
    permalink: /posts/{slug}/
    rss: false
    template:
      - index

That’s neat :+1:

In the rss template I was trying to get a handle on what data is available by putting {{log this}} in the template. This causes errors. Is there a suggested way of determining what data is available to a template?

No data is available by default – you can get some data using the {{#get}} helper so you can manually specify exactly what you do/don’t want to include in your RSS feed. This is useful, cause it means you can make an iTunes-compatible feed, rather than just a default feed :nerd_face:

(we’ll make some more detailed guides for things like this soon - just catching up from the launch atm)

Yeah that’s basically what I arrived at my self :slight_smile:

I’m very close to having it working. Not quite sure how I will encode the link to the mp3 nor the duration of the episode.

I suppose I could just dedicate the first 2 lines of the post to it and extract it in the template. It’s very much a hack though. Any ideas how to make that more generalisable?

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://www.rssboard.org/media-rss" version="2.0">
    <channel>
        <title>{{@blog.title}}</title>
        <link>{{@blog.url}}</link>
        <lastBuildDate>{{date format="ddd, D MMM YYYY HH:mm:ss ZZ"}}</lastBuildDate>
        <language>en-GB</language>
        <generator>Ghost {{data.safeVersion}}</generator>
        <itunes:author>{{@blog.authors}}</itunes:author>
        <itunes:subtitle>{{@blog.description}}</itunes:subtitle>
        <itunes:summary>{{@blog.description}}</itunes:summary>
        <description>{{@blog.description}}</description>
        <itunes:explicit>no</itunes:explicit>
        <itunes:owner>
            <itunes:name>melissa@bcuriouspodcast.com</itunes:name>
            <itunes:email>melissa@bcuriouspodcast.com</itunes:email>
        </itunes:owner>
        <itunes:category text="Business" />
        <itunes:image href="{{@blog.logo}}" />
        {{#get "posts" filter="tag:episode"}}
            {{#foreach posts}}
                <item>
                    <title>{{title}}</title>
                    <dc:creator>{{@blog.title}}</dc:creator>
                    <itunes:author>{{@blog.title}}</itunes:author>
                    <pubDate>{{date published_at format="ddd, D MMM YYYY HH:mm:ss ZZ"}}</pubDate>
                    <link>{{url absolute=true}}</link>
                    <guid isPermaLink="false">{{id}}</guid>
                    <description><![CDATA[{{content}}]]></description>
                    <itunes:subtitle>{{excerpt words="33"}}</itunes:subtitle>
                    <itunes:explicit>no</itunes:explicit>
                    <itunes:duration>02:08:14</itunes:duration>
                    <itunes:image href="{{@blog.logo}}" />
                    <content:encoded />
                    <enclosure url="http://traffic.libsyn.com/xx.mp3" length="61745629" type="audio/mpeg" />
                    <media:content url="http://traffic.libsyn.com/xx.mp3" length="61745629" type="audio/mpeg" isDefault="true" medium="audio" />
                </item>
            {{/foreach}}
        {{/get}}
    </channel>
</rss>

At the moment you’d definitely have to resort to some hacks. I would probably lean toward using the custom excerpt field, or maybe repurposing some of the social media description fields