Is there a way to skip the first featured post in a list of posts on the homepage?

Hello,

In my index.hbs file, I’m currently using the get helper to fetch the first featured post to display in a large block at the top of the screen, and foreach to display 10 more posts on the homepage. Here is my code:

    {{!-- Featured Post --}}
    {{#is "home"}}
    {{#get "posts" filter="featured:true" limit="1" as |featured_post|}}
        {{#foreach featured_post}}
            <article class="post featured">
                <header class="major">
                    <span class="date">{{date format="MMM D, YYYY"}}</span>
                    <h2><a href="{{url}}">{{title}}</a></h2>
                    <p>{{excerpt words="44"}}</p>
                </header>
                {{#if feature_image}}
                <a href="{{url}}" class="image main">
<img
    srcset="{{img_url feature_image size="s"}} 300w,
            {{img_url feature_image size="m"}} 600w,
            {{img_url feature_image size="l"}} 1000w,
            {{img_url feature_image size="xl"}} 2000w"
    sizes="(max-width:375px) 300px, (max-width:792px) 600px, 1000px"
src="{{img_url feature_image format="webp" size="l"}}" alt="{{title}}" /></a>
                {{/if}}
                <ul class="actions special">
                    <li><a href="{{url}}" class="button large">Read the Rest</a></li>
                </ul>
            </article>
        {{/foreach}}
    {{/get}}
    {{/is}}

    {{!-- Posts --}}
    <section class="posts">
        {{#foreach posts}}
            {{#if featured}}
                {{#is "home"}}
                    <article class="post featured">
                {{else}}
                    <article class="post">
                {{/is}}
            {{else}}
                    <article class="post">
            {{/if}}
                        <header>
                            <span class="date">{{date format="MMM D, YYYY"}}</span>
                            <h2><a href="{{url}}">{{title}}</a></h2>
                        </header>
                        {{#if feature_image}}
                        <a href="{{url}}" class="image fit"><img
                srcset="{{img_url feature_image size="s"}} 300w,
                        {{img_url feature_image size="m"}} 600w,
                        {{img_url feature_image size="l"}} 1000w,
                        {{img_url feature_image size="xl"}} 2000w"
                sizes="(max-width:375px) 300px, 600px"
            src="{{img_url feature_image format="webp" size="m"}}" loading="lazy" alt="{{title}}" /></a>
                        {{/if}}
                        <p>{{excerpt words="44"}}</p>
                        <ul class="actions special">
                            <li><a href="{{url}}" class="button">Read the Rest</a></li>
                        </ul>
                    </article>
        {{/foreach}}

    </section>

I am also using the following CSS via code injection to hide the first featured post, which would normally be duplicated in the list of posts below:

    section.posts > .featured {
        display: none;
    }
    section.posts > .featured ~ .featured {
      display: block;
    }

This successfully hides the first featured post from being displayed again, however since it’s still being included in the list and then hidden, only 9 posts show up in the list on the homepage.

My question: Is there a way to use Handlebars to exclude the first featured post (via either foreach or get) from the list of posts displayed on the homepage?

The challenge here is that you’re making a get request for featured content only, and then using the site’s pagination (defined by routes.yaml and config.production.json) to get a page of the most recent content, featured or not. The pagination doesn’t actually know if there’s a featured post in the first ten or not, which is why your theme developer is using the trick they are.

— option 1 —
Get 11 posts for the second section (switching to a get request rather than just foreach with the existing paginated route), and use css to hide the last one if there isn’t a .featured post in the group. Something like:

section.posts:not(:has(.featured)) post:nth-child(11) { 
  display: none; 
} 

— option 2 —
If you’re interested in restructuring the handlebars a bit, another option is to do this:

    {{!-- Featured Post --}}
    {{#is "home"}}
    {{#get "posts" filter="featured:true" limit="1" as |featured_post|}}
        {{#foreach featured_post}}
            <article class="post featured">
                 {{!-- article rendering skipped for brevity --}}
            </article>

             {{ > "your-new-partial" excludeId=id }}

        {{/foreach}}
    {{/get}}
    {{/is}}

And then in a new file: partials/your-new-partial.hbs:

    {{!-- Posts --}}
{{#get "posts" filter="id:-{{excludeId}}" limit="10" }} 
    <section class="posts">
        {{#foreach posts}}
              {{!-- article rendering skipped for brevity --}}
        {{/foreach}}
    </section>

Try this for your second loop. It should get you 10 posts except the featured post.

{{#get 'posts' filter='featured:true' limit='1'}}
  {{#get 'posts' filter='id:-[{{posts[*].id}}]' limit='10'}}
    {{#if posts}}
      {{#foreach posts}}
        {{ title }}<br>
      {{/foreach}}
    {{/if}}
  {{/get}}
{{/get}}
1 Like