/latest url that points to the newest page in a section


Let’s say this is my content hierarchy and i want a url that links to the most recently added post.
In the case of this image, it would link to secondpost.md.
https://example.com/posts/latest --> https://example.com/posts/secondpost.

Now when i add: “newestpost.md” to the posts section, i would like to be linked to this page instead:
https://example.com/posts/latest --> https://example.com/posts/newestpost.

I can’t seem to find anything in the docs that would support this but maybe you guys have any ideas?

Interesting idea. The only thing I can think of off the top of my head is, use an alias in the latest markdown. That’s manual and imo inelegant, though.

I wouldn’t try to solve this with Hugo, this looks like a dynamic that you could handle with Javascript.

Take a look here:

He uses a Json file to create a dynamic redirect in the 404 page. The same could be done with hugo, listing everything in a section and directing the user to the latest page in that section.

Create a “latest” section and use range to get the latest page

{{ range first 1  .Pages }}
    {{ .Content}}
{{ end }}

or generate a redirect to this page!


To add to @ju52 answer, you could sort by publish date in reverse too:

{{ range first 1 .Pages.ByPublishDate.Reverse }}

Tested with .Site.RegularPages. Works.

1 Like

In this case it does not work like a redirect right?
This creates a new page with url "https://example.com/posts/latest " that uses the content form the newest page of the posts section?

Right. It’s not a redirect, it’s an actual page.

1 Like

This is a pretty interesting approach, and might for my case be even better than a redirect.
But this will mean that when i range over all the pages of the “posts” section, this extra page will also show up, since the “latest” section is nested under the “posts” section.

In your posts section range, you can exclude that item

I have a moment so I will be specific.

  • Created /layouts/_default/latest.html based on my single.html because it had the right headers and footers already applied, then replaced the relevant code in the main block. See below.
  • Created /content/latest/_index.md with some basic frontmatter filled.

My latest.html layout defines the main block like this between header and footer sections:

{{ define "main" }}
<main class="a b">
  <article class="c d">
   <h1 class="e f">{{ .Title }}</h1>
          {{ range first 1 .Site.RegularPages.ByPublishDate.Reverse }}
          <h2 class="g h"><a class="link" href="{{ .Permalink }}">{{ .Title }}</a></h2>
          <h4 class="i j">{{ .Date.Format "Monday, 2 Jan, 2006" }}</h4>
            {{ .Content }}
          {{ end }}
  <a class="k l" href="/">Back to Home</a>
{{ end }}

The .Title on line 4 is that of the _index.md file. The other .Title inside the range loop is from the result page of the range. I like the focus of .Site.RegularPages better than the all-encompassing .Site.Pages so I used that.


Additionally, if I was really trying to put this into production, I would be concerned that, the section page’s date is coming from the _index.md which has to be manually updated, or scripted. One solution candidate is to use a git hook to run a script to increment the date, either lazily using today’s date, or, somehow copy-pasting the latest post’s date to the section page frontmatter.

Another point is, I’ve heard search engines penalize sites for having duplicate content. As a static page, this is truly a static and duplicate page. It kind of nudges me in the direction of javascript for this particular thing…

1 Like

Another solution is to set enableGitInfo to true and avoid the manual date all together

create partial latest.html with

{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "post")   }}
	<meta http-equiv="refresh" content="0; URL={{.RelPermalink}}" />

ans add in baseof.html

{{ partial "meta" . }}
{{if (eq .Type "latest") }}{{ partial "latest" . }}{{end}}

Then /latest will redirected.


categories  = ["latest"]
title       = "latest"

@ju52 thanks, that’s smart!