Microblogging, Ghost CMS, and RSS feeds

I've struggled for a long time getting Ghost to properly display posts without titles via RSS. It's been such a struggle, I've even moved away from the CMS entirely when I couldn't get it to do what I wanted despite following tutorials online.

Basic things like removing the titles of posts on the front page of the site or changing the page title in the head (that appears in tabs, for example) was easy enough but when viewing the posts via RSS reader or Micro.blog, they came out as "(Untitled)" alongside a link back to the post.

Using the custom RSS routing was tough for me to wrap my head around but I finally cracked it and, if you've struggled with the same, I want to share how I split out the post types into their own feeds and got them to display correctly:

  • Create a new tag for your micro/title-less posts. In this case, I've used the tag "Aside".
  • Download your routes.yaml file located in the Labs section of your admin.
  • Open routes.yaml in your text editor of choice.
  • Under "routes", add the following, ensuring you're tabbing appropriately:
/main/rss/:
	template: main_rss
	content_type: text/xml

/aside/rss/:
	template: aside_rss
	content_type: text/xml
  • Save your routes.yaml file and close it.
  • In your text editor, create a new file and paste the following into it:
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><![CDATA[ {{@blog.title}} ]]></title>
<description><![CDATA[ {{@blog.description}} ]]></description>
<link>{{@blog.url}}</link>
<image>
    <url>{{@blog.url}}/favicon.png</url>
    <title>{{@blog.title}}</title>
    <link>{{@blog.url}}</link>
</image>
<lastBuildDate>{{date format="ddd, DD MMM YYYY HH:mm:ss ZZ"}}</lastBuildDate>
<atom:link href="{{@blog.url}}" rel="self" type="application/rss+xml"/>
<ttl>60</ttl>

{{#get "posts" limit="all" filter="tag:aside" include="authors"}}
    {{#foreach posts}}
    <item>
        <description><![CDATA[ {{excerpt}} ]]></description>
        <link>{{url absolute="true"}}</link>
        <guid isPermaLink="false">{{id}}</guid>
        <category><![CDATA[ {{primary_tag}} ]]></category>
        <dc:creator><![CDATA[ {{primary_author.name}} ]]></dc:creator>
        <pubDate>{{date format="ddd, DD MMM YYYY HH:mm:ss ZZ"}}</pubDate>
        <media:content url="{{feature_image}}" medium="image"/>
        <content:encoded><![CDATA[ {{content}} ]]></content:encoded>
    </item>
    {{/foreach}}
{{/get}}

</channel>
</rss>
  • Key things to note about the above code is that it specifically pulls only posts tagged as "Aside" and that there is no title in the item being pulled in.
  • Save this file in your main theme directory as aside_rss.hbs.
  • While we could stop here after uploading the theme files and routes file, your untitled posts will still appear in your main feed, which isn't ideal. To address this, we'll make another feed with all your other posts.
  • Create a new file in your text editor and paste the following:
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><![CDATA[ {{@blog.title}} ]]></title>
<description><![CDATA[ {{@blog.description}} ]]></description>
<link>{{@blog.url}}</link>
<image>
    <url>{{@blog.url}}/favicon.png</url>
    <title>{{@blog.title}}</title>
    <link>{{@blog.url}}</link>
</image>
<lastBuildDate>{{date format="ddd, DD MMM YYYY HH:mm:ss ZZ"}}</lastBuildDate>
<atom:link href="{{@blog.url}}" rel="self" type="application/rss+xml"/>
<ttl>60</ttl>

{{#get "posts" limit="all" filter="tags:-aside" include="authors"}}
    {{#foreach posts}}
    <item>
        <title><![CDATA[ {{title}} ]]></title>
        <description><![CDATA[ {{excerpt}} ]]></description>
        <link>{{url absolute="true"}}</link>
        <guid isPermaLink="false">{{id}}</guid>
        <category><![CDATA[ {{primary_tag}} ]]></category>
        <dc:creator><![CDATA[ {{primary_author.name}} ]]></dc:creator>
        <pubDate>{{date format="ddd, DD MMM YYYY HH:mm:ss ZZ"}}</pubDate>
        <media:content url="{{feature_image}}" medium="image"/>
        <content:encoded><![CDATA[ {{content}} ]]></content:encoded>
    </item>
    {{/foreach}}
{{/get}}

</channel>
</rss>
  • Important things to note in the above code is that we're now pulling in all tags except "Aside" and you'll notice we are now showing the entry title in the feed.
  • Save this file in your main theme directory as main_rss.hbs.
  • Next, you'll want to pack up your theme in a zip file and upload it to your Ghost site via the Design page.
  • Next, go to the Labs page and upload your updated routes.yaml file from earlier.
  • Now, to test it out, visit https://YOUR-URL/aside/rss and you should see just the feed for your posts without titles.
  • Next, visit https://YOUR-URL/main/rss and you should see all your full posts without any of the ones without titles.
  • BONUS: On Micro.blog, under Account → Edit Feeds & Cross-posting, you can add these two feeds separately and have them then display your different types of posts correctly while still piping back to your site.

Future goals for this would be to have one single feed that handles this change to posts. I know it's fairly simple to do, I just wanted to get this out the door as quickly and cleanly as possible.

If you have any questions about this solution or you have a better one, feel free to get in touch on Micro.blog or by sending me an email.