Blog Template
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
Section titled “Location”└── theme └── templates └── blog.liquidThe blog Object
Section titled “The blog Object”The blog template has access to the blog object with these properties:
Core Properties
Section titled “Core Properties”| Property | Type | Description |
|---|---|---|
id | string | Unique identifier |
title | string | Blog name |
description | string | Blog description |
slug | string | URL-safe identifier |
image | media | Blog featured image |
| Property | Type | Description |
|---|---|---|
posts | array | Posts in this blog (sorted by publish date) |
Content
Section titled “Content”| Property | Type | Description |
|---|---|---|
theme | object | Theme-specific field values |
Metadata
Section titled “Metadata”| Property | Type | Description |
|---|---|---|
meta.title | string | SEO title |
meta.description | string | SEO description |
meta.image | media | SEO/OG image |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Basic Template Example
Section titled “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
Section titled “Working with Blog Posts”Featured Post
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Using Blog Components”Post Card Component
Section titled “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
Section titled “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 → </a> </section>{% endif %}Alternate Blog Templates
Section titled “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 viewAlternate templates appear in the CMS for editors to select per blog.