Basker Docs

Blog template

Reference for the blog object — the container for posts

The blog template renders blog index pages that list all posts within a blog. It provides pagination and filtering capabilities for browsing blog content.

Location

└── theme
    └── templates
        └── blog.liquid

The blog Object

The blog template has access to the blog object with these properties:

Core Properties

PropertyTypeDescription
idstringUnique identifier
titlestringBlog name
descriptionstringBlog description
slugstringURL-safe identifier
imagemediaBlog featured image

Posts

PropertyTypeDescription
postsarrayPosts in this blog (sorted by publish date)

Content

PropertyTypeDescription
themeobjectTheme-specific field values

Metadata

PropertyTypeDescription
meta.titlestringSEO title
meta.descriptionstringSEO description
meta.imagemediaSEO/OG image
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Basic Template Example

{% layout 'layouts/default.liquid' %}

{% capture content_for_layout %}
<div class="blog">
  <header class="blog-header">
    <h1>{{ blog.title }}</h1>

    {% if blog.description %}
      <p class="lead">{{ blog.description }}</p>
    {% endif %}
  </header>

  <div class="blog-posts">
    {% for post in blog.posts %}
      <article class="post-preview">
        {% if post.image %}
          <img
            src="{{ post.image | image_url: width: 400, height: 250 }}"
            alt="{{ post.title }}"
            loading="lazy"
          >
        {% endif %}

        <div class="post-preview__content">
          <h2>
            <a href="/posts/{{ post.slug }}">{{ post.title }}</a>
          </h2>

          {% if post.publishDate %}
            <time datetime="{{ post.publishDate }}">
              {{ post.publishDate | date: '%B %d, %Y' }}
            </time>
          {% endif %}

          {% if post.description %}
            <p>{{ post.description | truncate: 150 }}</p>
          {% endif %}

          <a href="/posts/{{ post.slug }}" class="read-more">Read more</a>
        </div>
      </article>
    {% endfor %}
  </div>
</div>
{% endcapture %}

Working with Blog Posts

Featured Post

Display the most recent post prominently:

{% if blog.posts.size > 0 %}
  {% assign featured_post = blog.posts.first %}

  <article class="featured-post">
    {% if featured_post.image %}
      <img
        src="{{ featured_post.image | image_url: width: 1200, height: 600 }}"
        alt="{{ featured_post.title }}"
        class="featured-post__image"
      >
    {% endif %}

    <div class="featured-post__content">
      {% if featured_post.categories.size > 0 %}
        <span class="category">{{ featured_post.categories.first }}</span>
      {% endif %}

      <h2>
        <a href="/posts/{{ featured_post.slug }}">{{ featured_post.title }}</a>
      </h2>

      {% if featured_post.publishDate %}
        <time datetime="{{ featured_post.publishDate }}">
          {{ featured_post.publishDate | date: '%B %d, %Y' }}
        </time>
      {% endif %}

      {% if featured_post.description %}
        <p class="lead">{{ featured_post.description }}</p>
      {% endif %}

      <a href="/posts/{{ featured_post.slug }}" class="btn">Read Article</a>
    </div>
  </article>

  {# Remaining posts #}
  {% if blog.posts.size > 1 %}
    <div class="post-grid">
      {% for post in blog.posts offset: 1 %}
        {% render 'components/post-card' post: post %}
      {% endfor %}
    </div>
  {% endif %}
{% endif %}

Posts with Authors

{% for post in blog.posts %}
  <article class="post-item">
    <h2><a href="/posts/{{ post.slug }}">{{ post.title }}</a></h2>

    <div class="post-meta">
      {% if post.authors.size > 0 %}
        <span class="authors">
          By
          {% for author in post.authors %}
            {{ author.name }}{% unless forloop.last %}, {% endunless %}
          {% endfor %}
        </span>
      {% endif %}

      {% if post.publishDate %}
        <time datetime="{{ post.publishDate }}">
          {{ post.publishDate | date: '%b %d, %Y' }}
        </time>
      {% endif %}
    </div>
  </article>
{% endfor %}

Posts Grouped by Month

{% assign current_month = '' %}

{% for post in blog.posts %}
  {% assign post_month = post.publishDate | date: '%B %Y' %}

  {% if post_month != current_month %}
    {% unless current_month == '' %}
      </div>
    {% endunless %}
    <h3 class="month-header">{{ post_month }}</h3>
    <div class="month-posts">
    {% assign current_month = post_month %}
  {% endif %}

  {% render 'components/post-card' post: post %}

  {% if forloop.last %}</div>{% endif %}
{% endfor %}

Posts by Category

Display posts filtered by category:

{# Get unique categories from all posts #}
{% assign all_categories = '' %}
{% for post in blog.posts %}
  {% for category in post.categories %}
    {% unless all_categories contains category %}
      {% if all_categories != '' %}
        {% assign all_categories = all_categories | append: ',' %}
      {% endif %}
      {% assign all_categories = all_categories | append: category %}
    {% endunless %}
  {% endfor %}
{% endfor %}
{% assign categories = all_categories | split: ',' %}

{# Category filter navigation #}
<nav class="category-filter">
  <a href="/blogs/{{ blog.slug }}" class="filter-link {% unless request.params.category %}active{% endunless %}">
    All
  </a>
  {% for category in categories %}
    <a href="/blogs/{{ blog.slug }}?category={{ category | handleize }}"
       class="filter-link {% if request.params.category == category | handleize %}active{% endif %}">
      {{ category }}
    </a>
  {% endfor %}
</nav>

Working with Theme-Specific Fields

Access custom fields defined in the template schema via blog.theme:

{# Template schema defines: posts_per_page, show_featured, newsletter_signup #}

{% if blog.theme.show_featured and blog.posts.size > 0 %}
  {% assign featured = blog.posts.first %}
  {# Display featured post #}
{% endif %}

{% if blog.theme.newsletter_signup.enabled %}
  <aside class="newsletter-signup">
    <h3>{{ blog.theme.newsletter_signup.heading | default: 'Subscribe' }}</h3>
    <p>{{ blog.theme.newsletter_signup.description }}</p>
    <form action="{{ blog.theme.newsletter_signup.form_action }}" method="post">
      <input type="email" name="email" placeholder="Your email" required>
      <button type="submit">Subscribe</button>
    </form>
  </aside>
{% endif %}

Complete Template Example

{% layout 'layouts/default.liquid' %}

{% capture content_for_layout %}
<div class="blog-page">
  {# Blog header #}
  <header class="blog-header">
    {% if blog.image %}
      <img
        src="{{ blog.image | image_url: width: 1920, height: 400 }}"
        alt="{{ blog.title }}"
        class="blog-header__image"
      >
    {% endif %}

    <div class="blog-header__content">
      <h1>{{ blog.title }}</h1>

      {% if blog.description %}
        <p class="lead">{{ blog.description }}</p>
      {% endif %}
    </div>
  </header>

  {% if blog.posts.size > 0 %}
    {# Featured post #}
    {% if blog.theme.show_featured != false %}
      {% assign featured = blog.posts.first %}

      <section class="featured-section">
        <article class="featured-post">
          {% if featured.image %}
            <a href="/posts/{{ featured.slug }}" class="featured-post__image-link">
              <img
                src="{{ featured.image | image_url: width: 1200, height: 500 }}"
                alt="{{ featured.title }}"
                class="featured-post__image"
              >
            </a>
          {% endif %}

          <div class="featured-post__content">
            {% if featured.categories.size > 0 %}
              <span class="featured-post__category">{{ featured.categories.first }}</span>
            {% endif %}

            <h2 class="featured-post__title">
              <a href="/posts/{{ featured.slug }}">{{ featured.title }}</a>
            </h2>

            <div class="featured-post__meta">
              {% if featured.publishDate %}
                <time datetime="{{ featured.publishDate }}">
                  {{ featured.publishDate | date: '%B %d, %Y' }}
                </time>
              {% endif %}

              {% if featured.authors.size > 0 %}
                <span class="author">
                  by {{ featured.authors.first.name }}
                </span>
              {% endif %}
            </div>

            {% if featured.description %}
              <p class="featured-post__excerpt">{{ featured.description }}</p>
            {% endif %}

            <a href="/posts/{{ featured.slug }}" class="btn btn--primary">
              Read Article
            </a>
          </div>
        </article>
      </section>
    {% endif %}

    {# Posts grid #}
    <section class="posts-section">
      <h2 class="visually-hidden">All Posts</h2>

      <div class="post-grid">
        {% assign offset = 0 %}
        {% if blog.theme.show_featured != false %}
          {% assign offset = 1 %}
        {% endif %}

        {% for post in blog.posts offset: offset %}
          <article class="post-card">
            <a href="/posts/{{ post.slug }}" class="post-card__link">
              {% if post.image %}
                <img
                  src="{{ post.image | image_url: width: 400, height: 250 }}"
                  alt="{{ post.title }}"
                  class="post-card__image"
                  loading="lazy"
                >
              {% endif %}

              <div class="post-card__content">
                {% if post.categories.size > 0 %}
                  <span class="post-card__category">{{ post.categories.first }}</span>
                {% endif %}

                <h3 class="post-card__title">{{ post.title }}</h3>

                <div class="post-card__meta">
                  {% if post.publishDate %}
                    <time datetime="{{ post.publishDate }}">
                      {{ post.publishDate | date: '%b %d, %Y' }}
                    </time>
                  {% endif %}
                </div>

                {% if post.description %}
                  <p class="post-card__excerpt">
                    {{ post.description | truncate: 120 }}
                  </p>
                {% endif %}
              </div>
            </a>
          </article>
        {% endfor %}
      </div>
    </section>

  {% else %}
    <div class="blog-empty">
      <p>No posts yet. Check back soon!</p>
    </div>
  {% endif %}

  {# Newsletter signup #}
  {% if blog.theme.newsletter_signup_enabled %}
    <aside class="newsletter-section">
      <div class="newsletter-content">
        <h3>{{ blog.theme.newsletter_heading | default: 'Stay Updated' }}</h3>
        <p>{{ blog.theme.newsletter_description | default: 'Subscribe to get the latest posts delivered to your inbox.' }}</p>
        <form class="newsletter-form" action="{{ blog.theme.newsletter_action }}" method="post">
          <input type="email" name="email" placeholder="Enter your email" required>
          <button type="submit" class="btn btn--primary">Subscribe</button>
        </form>
      </div>
    </aside>
  {% endif %}
</div>
{% endcapture %}

{% schema %}
{
  "name": "blog",
  "settings": [
    {
      "type": "checkbox",
      "name": "show_featured",
      "label": "Show Featured Post",
      "defaultValue": true
    },
    {
      "type": "number",
      "name": "posts_per_page",
      "label": "Posts Per Page",
      "defaultValue": 12
    },
    {
      "type": "checkbox",
      "name": "newsletter_signup_enabled",
      "label": "Enable Newsletter Signup",
      "defaultValue": false
    },
    {
      "type": "text",
      "name": "newsletter_heading",
      "label": "Newsletter Heading"
    },
    {
      "type": "textarea",
      "name": "newsletter_description",
      "label": "Newsletter Description"
    },
    {
      "type": "text",
      "name": "newsletter_action",
      "label": "Newsletter Form Action URL"
    }
  ]
}
{% endschema %}

Using Blog Components

Post Card Component

{# components/post-card.liquid #}
{#
  Required: post (post object)
  Optional: show_category (boolean), show_excerpt (boolean)
#}
{% assign show_category = show_category | default: true %}
{% assign show_excerpt = show_excerpt | default: true %}

<article class="post-card">
  <a href="/posts/{{ post.slug }}" class="post-card__link">
    {% if post.image %}
      <img
        src="{{ post.image | image_url: width: 400, height: 250 }}"
        alt="{{ post.title }}"
        class="post-card__image"
        loading="lazy"
      >
    {% endif %}

    <div class="post-card__content">
      {% if show_category and post.categories.size > 0 %}
        <span class="post-card__category">{{ post.categories.first }}</span>
      {% endif %}

      <h3 class="post-card__title">{{ post.title }}</h3>

      {% if post.publishDate %}
        <time class="post-card__date" datetime="{{ post.publishDate }}">
          {{ post.publishDate | date: '%b %d, %Y' }}
        </time>
      {% endif %}

      {% if show_excerpt and post.description %}
        <p class="post-card__excerpt">{{ post.description | truncate: 120 }}</p>
      {% endif %}
    </div>
  </a>
</article>

Recent Posts Section

For use on other pages:

{# Display recent posts from a specific blog #}
{% assign news_blog = all_blogs | where: 'slug', 'news' | first %}

{% if news_blog.posts.size > 0 %}
  <section class="recent-posts">
    <h2>Latest News</h2>

    <div class="post-grid">
      {% for post in news_blog.posts limit: 3 %}
        {% render 'components/post-card' post: post %}
      {% endfor %}
    </div>

    <a href="/blogs/{{ news_blog.slug }}" class="view-all-link">
      View All Posts &rarr;
    </a>
  </section>
{% endif %}

Alternate Blog Templates

Create variations for different blog styles:

templates/
├── blog.liquid           # Default blog listing
├── blog.magazine.liquid  # Magazine-style layout
├── blog.minimal.liquid   # Minimal text-focused
└── blog.grid.liquid      # Grid gallery view

Alternate templates appear in the CMS for editors to select per blog.

On this page