Dynamic routing for next/previous post helper

As mentioned in a previous thread, it’s not possible to exclude tags from the next/previous post functionality. I believe this would be useful to have, or even better, dynamic routing for the next/previous post helper, as I’ll explain with three use-cases.

  1. I’m putting together the theme for a colleague that I’m migrating from Medium to Ghost. Not only does he have his own publication, but he is also published on many external sites. I got the idea to create quasi-posts for all of his external articles, quasi-posts which only display the feature image and title. The feature images and titles for these quasi-posts are displayed in the footer as well as on a dedicated page via a channel I created thanks to dynamic routing. Moreover, rather than reproduce these articles in their entirety I utilized the canonical URL field so that clicking on the title/feature image of one of these quasi-posts sends the reader to the external site where the entire article exists. Separate from this I wanted to add in next/previous post functionality to posts in the main blog feed, but then found out that the external articles that don’t appear in the main blog feed do however appear within the next/previous post “feed”. As there was no way around this I had to exclude the next/previous post helper from this theme.

  2. I’ve put together a spec theme for another colleague (currently on WordPress), a colleague who has included/duplicated a couple of older/tiny “sub-blogs” as side-portions within his blog. I’ve reproduced all this in Ghost with channels/dynamic routing, although as I’ve noticed, the next/previous post functionality of the main blog feed is now “polluted” with posts from those other sub-blogs. I suppose I could rectify all this by changing all the posts of those sub-blogs to pages and then using a whole lot of routes rather than two channels, but I’d rather not do that if I didn’t have to.

  3. I’ve had several posts from my personal blog translated to various languages. For a while now I’ve had them reproduced on my blog as pages, but just last week I got the idea to move them to posts and separate them all with channels. Works great. However, and as I just belatedly clued in (read: I should have known better), I’ve just somewhat messed things up since the translated posts now appear within the next/previous post section of posts in the main blog feed, which are not only out of place but also create all sorts of dead-ends and such (since translated posts don’t include the next/previous helper). Whoops.

Thanks for sharing these scenarios! Always interesting to know how Ghost is being used for various projects :rainbow:

Just to clarify, have you checked out the in parameter that can be used with #next_post and #prev_post?

This could be used in conjunction with tags to filter out, or in, posts depending on whether they should appear in the single post pagination :page_facing_up:

Yes, as you can see in the thread that I linked to at the top of my original post, @jbfriedrich (who I messaged with) was also trying to exclude tags from #next_post and #prev_post but couldn’t get it to work. Nonetheless, are you saying that there is in fact a way to exclude posts (such as by using out instead of in)? Or are you suggesting that in a roundabout way one could exclude posts by creating an overarching primary_tag for all the posts in the main blog feed and then making sure that all the other posts in the various Channels one has set up don’t have that primary_tag?

If it’s the latter case then that’d fix one problem but potentially create even more problems in the process. By including in="primary_tag" in the #next_post and #prev_post helpers that’d mean that all my (use-case #3) non-translated posts would have to have the same primary tag (English? Non-Translated?). That’d obviously look a bit weird in the tag list.

Secondly, and at the bottom of each post, my theme (and my colleague’s theme from use-case #1) get and display links to a few related posts, the get based on the primary_tag. If every post from the main blog feed had to have the same primary_tag then this would make the “related posts” section kind of ineffectual.

Last of all, I’ve set up the spec theme for my colleague’s theme from use-case #2 to have a stylized primary_tag above the post’s title, which would again be rather ineffectual if the primary_tag for all the posts in the main blog feed had to be Main-blog or something.

That all being said, if you know of someway to exclude tags from the #next_post and #prev_post helpers then that’d totally negate the need for my suggestion of “Dynamic routing for next/previous post helper”. :slightly_smiling_face:

The example there is a little misleading, but I believe it can be any tag and not just the primary tag. In theory you could put the tag last so it wouldn’t be the primary one? There’s also the concept of “internal” tags https://ghost.org/docs/api/v2/handlebars-themes/helpers/tags/#the-visibility-attribute I’d need to test this but you could use these tags to help determine where posts should be shown but they wouldn’t be exposed in the front-end.

Thanks again for the reply David. I was glad to hear “I believe it can be any tag and not just the primary tag”, and although I wouldn’t want a final “English” tag added to every post on my blog (and certainly not to my colleagues’ blogs), an internal tag would be a pain-in-the-arse but doable. Unfortunately, I don’t think it worked, be they internal or external tags.

Supposing the tag one wants to use is “ghost”, I first tried {{#next_post in="#ghost"}} and {{#prev_post in="#ghost"}}. Nothing happened. Then (and to truncate things a bit), in="hash-ghost". Nope.

To see if anything at all worked I tried in="primary_tag" (as is shown in the docs). That worked.

Thinking that it perhaps didn’t like internal tags I tried in="ghost", in="tag_ghost" and in="ghost_tag". None of those worked.

Did I possibly miss some other combo that might do the trick? :crossed_fingers:

Hmm, maybe I’ve misread the docs myself :face_with_head_bandage:. I may have to come back to this one. In the interim I did find this Stackoverflow thread where someone had used the #get helper to get the next and previous posts and used the filter option within #get:

1 Like

I am not a JS expert, but it looks like you can either specify nothing, then you get the next/prev posts based on date or you can specify a primary tag / primary author. This is from prev_next.js, line 38 to 46:

if (_.get(options, 'hash.in')) {
    if (options.hash.in === 'primary_tag' && _.get(post, 'primary_tag.slug')) {
        apiOptions.filter += '+primary_tag:' + post.primary_tag.slug;
    } else if (options.hash.in === 'primary_author' && _.get(post, 'primary_author.slug')) {
        apiOptions.filter += '+primary_author:' + post.primary_author.slug;
    } else if (options.hash.in === 'author' && _.get(post, 'author.slug')) {
        apiOptions.filter += '+author:' + post.author.slug;

It defines different filter settings based on what arguments are provided (author will be removed with Ghost 3.0 it seems). I think this would need to be extended if one wants a more extensive behavior. Right now you cannot include/exclude tags. You can only say “give me a previous/next post by date and where primary_tag/primary_author is X”. Unless I am reading all this wrong :slight_smile: .

1 Like

@DavidDarnes Thanks again for this. Unfortunately I couldn’t get it to work, no matter how many combos I tried. From what I’ve been told, by somebody more knowledgeable about this stuff than I,

id:<{{id}} won’t work. IDs are programatically generated and are not numbers.

Perhaps it did work in the past but does not now due to the post being two years (and one day) old and Ghost having changed since then?

@jbfriedrich Awesome, thanks for pointing this out! I’d totally contribute the code to address this myself, although not only am I also not a JS expert, but the extent of my knowledge is that “JS” means “JavaScript”. :sweat_smile: