Featured Posts

Highlight featured content in sidebars and homepages

4 min read 751 words

Highlight important content using thefeaturedfrontmatter flag.

Note

Built into Default Theme

Bengal's default theme recognizesfeatured: truefrontmatter:

  • Shows "⭐ Featured" badge on article cards
  • For badge display only:tags: [featured]works via theis featuredtest

Important: Thesection.featured_posts()method only checksfeatured: truein metadata, not tags. Usefeatured: truefor featured post collections.

This recipe shows how to create featured sections, hero layouts, and sidebar widgets.

The Pattern

Frontmatter Setup

Mark posts as featured:

---
title: "Our Most Important Post"
featured: true
---

Template Code

{% let featured = section.featured_posts(3) %}

{% if featured %}
<section class="featured-posts">
  <h2>Featured</h2>
  {% for post in featured %}
  <article class="featured-card">
    <h3><a href="{{ post.href }}">{{ post.title }}</a></h3>
    <p>{{ post.description }}</p>
  </article>
  {% end %}
</section>
{% end %}

Note:section.featured_posts(limit)is a method that returns featured posts sorted by date (newest first). Default limit is 5 if omitted.

What's Happening

Property/Method Purpose
section.featured_posts(limit) Method returning pages withfeatured: true, sorted by date (newest first). Default limit: 5
page.metadata.featured Check if a page is featured (boolean)
page is featured Template test checking if page has'featured'tag (for badge display)

Sorting: Featured posts are automatically sorted by date descending (newest first). To sort by custom priority, usesort_by('metadata.featured_priority')after calling the method.

Variations

Single featured post as hero:

{% let hero = section.featured_posts(1) |> first %}

{% if hero %}
<header class="hero">
  {% if hero.metadata.cover_image %}
  <img src="{{ hero.metadata.cover_image }}" alt="">
  {% end %}
  <div class="hero-content">
    <span class="label">Featured</span>
    <h1><a href="{{ hero.href }}">{{ hero.title }}</a></h1>
    <p>{{ hero.description }}</p>
    <a href="{{ hero.href }}" class="btn">Read More</a>
  </div>
</header>
{% end %}
{% let all_posts = section.sorted_pages %}
{% let featured = section.featured_posts(3) %}
{% let regular = all_posts |> complement(featured) |> limit(10) %}

<div class="posts-layout">
  <aside class="featured-sidebar">
    <h3>Featured</h3>
    {% for post in featured %}
    <article class="featured-item">
      <a href="{{ post.href }}">{{ post.title }}</a>
    </article>
    {% end %}
  </aside>

  <main class="posts-main">
    {% for post in regular %}
    <article>
      <h2><a href="{{ post.href }}">{{ post.title }}</a></h2>
      <p>{{ post.excerpt }}</p>
    </article>
    {% end %}
  </main>
</div>
{% for post in section.sorted_pages %}
<article class="{% if post.metadata.featured %}is-featured{% end %}">
  {% if post.metadata.featured %}
  <span class="badge">⭐ Featured</span>
  {% end %}
  <h2><a href="{{ post.href }}">{{ post.title }}</a></h2>
</article>
{% end %}
{% let featured = section.featured_posts(4) %}

<div class="featured-grid">
  {% for post in featured %}
  <article class="grid-item">
    {% if post.metadata.cover_image %}
    <img src="{{ post.metadata.cover_image }}" alt="">
    {% end %}
    <div class="content">
      <h3><a href="{{ post.href }}">{{ post.title }}</a></h3>
      <time>{{ post.date | date('%B %d, %Y') }}</time>
    </div>
  </article>
  {% end %}
</div>

Get featured posts from any section:

{% let all_featured = site.pages |> where('metadata.featured', true) |> limit(5) %}

<section class="site-featured">
  <h2>Editor's Picks</h2>
  {% for post in all_featured %}
  <a href="{{ post.href }}">
    <span class="section-name">{{ post.section }}</span>
    {{ post.title }}
  </a>
  {% end %}
</section>

Support priority ordering:

---
featured: true
featured_priority: 1  # Lower = higher priority
---
{% let featured = section.featured_posts() |> sort_by('metadata.featured_priority') %}

Note:featured_priorityis a custom metadata field. Posts are sorted by this field (ascending, so lower numbers appear first), then by date if priority is equal.

Show different featured posts based on day:

{% let featured = section.featured_posts() %}
{% let today_index = now().timetuple().tm_yday % (featured | length) %}
{% let todays_featured = featured[today_index] %}

<aside class="daily-pick">
  <h3>Today's Pick</h3>
  <a href="{{ todays_featured.href }}">{{ todays_featured.title }}</a>
</aside>

Example CSS

.featured-card {
  border: 2px solid var(--accent);
  border-radius: 8px;
  padding: 1.5rem;
  background: var(--bg-secondary);
}

.featured-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.grid-item {
  position: relative;
  border-radius: 8px;
  overflow: hidden;
}

.grid-item img {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.grid-item .content {
  padding: 1rem;
  background: linear-gradient(transparent, rgba(0,0,0,0.8));
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  color: white;
}

.is-featured {
  border-left: 4px solid var(--accent);
  padding-left: 1rem;
}

.badge {
  display: inline-block;
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  background: var(--accent);
  color: white;
  border-radius: 4px;
}

Seealso