Show different number of posts on first page

I have around 60 posts which I am displaying on the home page using .Paginate. (I’m using a modified version of the Stack theme, if it’s relevant.) I have a grid of posts, 6 to a page (2 rows of 3).

However, on the home page, I want to show the most recent post as featured. So it will be big, and will actually take up the whole first row of the grid. Ultimately, the first page of home will show 4 posts (1+3) whereas all other pages will show 6 (3+3).

I don’t know how to achieve this. I know I can exclude the first post from the list of paginated items, but that doesn’t seem to solve the problem of the first page having a different number of items than the others. I could ignore the pagination entirely on the first page and only start it on page 2 (I think? how?), but then the pagination will be out of sync (page 1 of the pagination will actually be /page/2). (I think this is the solution arrived at in this thread, although I don’t understand how OP avoided the page number sync problem.)

Here’s how it looks now, showing 6 posts on every page (config.json has paginate: 6):

    {{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
    {{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }}
    {{ $filtered := ($pages | intersect $notHidden) }}
    {{ $pag := .Paginate ($filtered) }}

    <section class="article-list">
        {{ range $index, $element := $pag.Pages }}
            {{ partial "article-list/default" . }}
        {{ end }}
    </section>

    {{- partial "pagination.html" . -}}

As soon as I work this out, I’ll need to pass the info along to the partials somehow, to update the CSS so that only the first post on the first page is styled large; every other first post on a page should be 1/3 of a row. (I’m using CSS Grid to lay out the grid.)

I’m still new to Hugo, perhaps I’m missing something obvious. A pointer to some sample code would be really helpful!

Thanks in advance for your thoughts.

Similar to:
https://discourse.gohugo.io/t/36186/2

Prepend two copies of the home page to your page collection, then ignore them.

{{ $p := where site.RegularPages "Type" "post" }}
{{ $p = (slice site.Home site.Home) | append $p }}

{{ range (.Paginate $p 6).Pages }}
  {{ if not .IsHome }}
    <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
  {{ end }}
{{ end }}

{{ template "_internal/pagination.html" . }}

Thank you for this suggestion! Unfortunately, it’s not working for me. I’m using hugo v0.91.2+extended.

    {{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
    {{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }}
    {{ $filtered := ($pages | intersect $notHidden) }}

    {{/* https://discourse.gohugo.io/t/show-different-number-of-posts-on-first-page/36418 */}}
    {{ $padded := (slice site.Home site.Home) | append $filtered }}
    {{ $pag := .Paginate ($padded) 6 }}

    <section class="article-list">
        {{ range $index, $element := $pag.Pages }}
            {{ if not $element.IsHome }}
                {{ partial "article-list/default" $element }}
            {{ end }}
        {{ end }}
    </section>

I see the two home pages being prepended to the $padded slice. But loading / still shows 6 posts starting from the first element of $filtered. If I remove the if not $element.IsHome piece, I still get the same 6 posts. The only thing I can think of is that I’m running into the caching issue discussed in the docs. But there’s only one call to Paginate in /layouts/index.html where this code is. I’ve looked at all the other places where Paginate or Pagination appears in the code, and none appear to be called before the code listed above.

So I’m stumped.

Aaaaah, I found the place that .Paginate was being called before the code above. It’s working now! Thank you for your help!

@nk9 how did you get your CSS to work for the first item only?

Here’s the code I ended up with for that. It relies on the fact the there is only ever one paginator on a page, and it’s created beforehand (with the code from before). $hasPrev needs to be saved before the range because the context gets reset inside, so .Paginator no longer exists.

<section class="article-list">
    {{ $hasPrev := .Paginator.HasPrev }}
    {{ range $index, $element := .Paginator.Pages }}
        {{ if not $element.IsHome }}
            {{ if and (not $hasPrev) (eq $index 2) }}
                {{ partial "article-list/featured" $element }}
            {{ else }}
                {{ partial "article-list/default" $element }}
            {{ end }}
        {{ end }}
    {{ end }}
</section>

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.