How can I determine the first page of posts?
What I want to do is find any page of posts that is not the first page so I can add a robots.txt tag to noindex. I don’t want search engines to index any other paginated pages than the first page of posts.
I’m using this is head.html:
{{ $homepage := .Paginate ( where .Site.RegularPages “Type” “posts” ) 5 }}
{{ if $homepage.HasPrev }}
{{ else }}
{{ end }}
but it throws the error <$homepage.HasPrev>: error calling HasPrev: runtime error: invalid memory address or nil pointer dereference
.
That error might be from two instances of the paginator, which I call as a partial paginator.html
later on in list.html.
Or, is there a better way to determine the first page of posts with a function other than Paginate?
I would use robots.txt
.
User-agent: *
Disallow: /*page/*
If you have configured a different pagination path (paginatePath
) in config.toml, replace ‘page’ with the value of paginatePath
.
But wait, won’t this stop the first page in a paginated list from being indexed? No, because requests for /foo/page/1
are always redirected to /foo/
via a meta-refresh, and /foo/
is allowed in this example of a robots.txt file.
There are several “robots.txt” testing tools to help with the syntax.
Thanks, I’m aware of robots.txt files and noindex directives; but I want to determine the first page of paginated posts in Hugo, both to not have users need to edit or be aware of robots.txt, and for other code reasons.
{{- with .Paginator -}}
{{- if and .HasNext (not .HasPrev) -}}
I am the first page.
{{- end -}}
{{- if and .HasPrev (not .HasNext) -}}
I am the last page.
{{- end -}}
{{- if and .HasNext .HasPrev -}}
I am neither the first nor the last page.
{{- end -}}
{{- end -}}
Thanks, that’s interesting and it works, but it breaks the Paginator, which I call as a partial paginator.html
later on in list.html for pagination in the post footer. The breakage results in listing all pages and posts, rather than simply posts. So I need to find some way to determine the first page and other paginated pages without using Paginator.
I hope you’ve made some progress, because I have not.
I’ve got a test site with this layout structure:
baseof
partial head
partial header
block main
(includes single or list)
partial footer
I tried setting a Scratch variable within list
:
{{- with .Paginator -}}
{{- if and .HasNext (not .HasPrev) -}}
{{- $.Scratch.Set "foo" "I am the first page." -}}
{{- end -}}
{{- if and .HasPrev (not .HasNext) -}}
{{- $.Scratch.Set "foo" "I am the last page." -}}
{{- end -}}
{{- if and .HasNext .HasPrev -}}
{{- $.Scratch.Set "foo" "I am neither the first nor the last page." -}}
{{- end -}}
{{- end -}}
Then I added this to head
:
{{- .Scratch.Get "foo" -}}
But, predictably, when accessed from head
, the value is null or incorrect, presumably due to rendering sequence or lack thereof (parallelism).
So, then I thought, “Oh well, let’s just parse .RelPermalink
to see if it ends with page/n
.” But the value of .RelPermalink
is the same for all pagers. For example:
URL Shown in Browser |
.RelPermalink |
/post/page/2/ |
/post/ |
/post/page/3/ |
/post/ |
/post/page/4/ |
/post/ |
And of course, /post/page/1 simply redirects to /post/, where the .RelPermalink is /post/
as expected. So, from inside head
I have no idea where I am. That’s quotable.
The only solution I’ve come up with is to change the layout structure. If list
were the top level (meaning no baseof
) we could instantiate the paginator at the top of the template, then set values in head
.