[SOLVED] Get the first and last post in a section (date-based)

I want to write a menu for my blog, and the should be links in the menu to the first and the last post. Please notice: This is not only on list pages, it’s the same on normal single pages. It’s on the header which is everywhere used.

While there is an obvious workaround for the URL to the first post (because it’s the first post and so it doesn’t change I can just hardcode the URL) it’s much harder for the lastpost ones. I don’t want to change this manually every time I create a new post.

Look at the first and last functions…

This only works on my list page, because I can’t use .Data.Pages or .Pages on a normal single page. Look here : .Pages a collection of associated pages. This will be nil for regular content pages. I took this from that doc page: https://gohugo.io/templates/variables/ .
Thank you for the answer, but it didn’t work : (

@asqiir The last post i.e. the oldest post is a given so why not just use its .Permalink in the menu.

But the first post i.e. the most recent post is a different matter.

And you are right.

It is not easy to render the .Permalink of the most recent content in a section, while in a content or regular page, in Hugo. In nodes and the homepage it’s a piece of cake. But not while on a content page and that is very strange.

I’ve been looking into this and I can’t seem to find a workable solution either.

Maybe @bep could enlighten us. Or @michael_henderson who made a post (a while back) about a web comic theme (I can’t seem to find anymore).

{{ $mysection := ($.Site.GetPage "section" .Section).Pages }}
{{ range first 1 $mysection }}
  FIRST: {{ .RelPermalink }}
{{ end }}
{{range last 1 $mysection }}
  LAST: {{ .RelPermalink }}
{{ end }}
1 Like

Have you tested this? .Pages does not work on single pages.

I’ve just tested what you posted and here is the output in my terminal.

ERROR 2017/05/26 23:33:51 Error while rendering "page": template: theme/_default/single.html:4:14: executing "theme/_default/single.html" at <partial "nav.html" .>: error calling partial: template: theme/partials/nav.html:20:43: executing "theme/partials/nav.html" at <.Section>: can't evaluate field Pages in type *hugolib.Page
ERROR 2017/05/26 23:33:51 Error while rendering "home": template: theme/index.html:3:19: executing "theme/index.html" at <partial "nav.html" .>: error calling partial: template: theme/partials/nav.html:20:43: executing "theme/partials/nav.html" at <.Section>: can't evaluate field Pages in type *hugolib.Page
ERROR 2017/05/26 23:33:51 Error while rendering "404": template: theme/404.html:4:15: executing "theme/404.html" at <partial "nav.html" .>: error calling partial: template: theme/partials/nav.html:20:43: executing "theme/partials/nav.html" at <.Section>: can't evaluate field Pages in type *hugolib.Page

That’s not a single page that @jgreely is grabbing. He’s grabbing the index page; i.e., the page with the kind of section. That’s the cool part about the .GetPage function. Try this instead if you are looking specifically for posts:

<!--Sorts pages by the publishdate field in front matter; you could use by date as well; the reverse puts the newest at the front-->
{{$posts := ($.Site.GetPage "section" "posts").Pages.ByPublishDate.Reverse}}
<!--Grab the most recent-->
{{ range first 1 $posts }}
<p>Most recent: {{.Title}} {{.PublishDate}}</p>
{{ end }}
<!--Grab the oldest-->
{{ range last 1 $posts }}
<p>Oldest: {{.Title}} {{.PublishDate}}</p>
{{ end }}

Also @jgreely 's solution will work if done within, for example, a partial that is embedded in a single.html since .Section will pull from the value for that particular rendered page…

1 Like

Also @asqiir note that the default ordering is weight => date for lists:

https://hugodocs.info/templates/lists/#ordering-content

OK. I just got it. Haven’t tested it yet.

But it seems a bit convoluted for getting the URL of the most recent post. Doesn’t it?

I mean Jekyll does this thing with {{ site.posts.last.url }}

Why do we have to use a partial for something as simple as getting the first post site wide?

EDIT
And thank you @rdwatters for clarifying this.

2 Likes

You don’t need to. Well, to be clearer, you could use partialCached since it’s always going to return the same value and you probably don’t want it to affect your build time. The templating I provided above was building on the previous example using .GetPage, but you could just as easily do this with a where statement and first and range.

Comparisons to Jekyll seem out of place here since what you pay for in templating terseness with Hugo you get back in astronomically improved build times…

Liquid is great to start, but I’m convinced that Hugo/Golang templates are much more powerful; it just takes a minute to get used to the syntax :smile:

Ok. Again thanks.

1 Like

I tested it quite successfully, inside of a section. Unfortunately, when rendering the homepage, .Section is “”, and $.Site.GetPage "section" .Section returns (*hugolib.Page)(nil).

To cover the case where you want to put it on the homepage as well, you’d have to use:

$.Site.GetPage "section" .Section | default ($.Site.GetPage "home")
1 Like

No worries. @rdwatters cleared up everything. Thanks for your input also.

1 Like

I ended with that code:

{{ $all := ($.Site.GetPage "section" .Section).Pages.ByPublishDate.Reverse }} {{ range first 1 $all }} {{ .Permalink }} {{ end }}

Important: turn all in one line and remove all spaces! Without that won’t be a valid URL.
Thank you for helping me!

What do you mean?