Category template
Reference for the category object — primary post groupings within a blog
The category template renders pages that display all posts within a specific category. It provides a filtered view of blog content organized by category.
Location
└── theme
└── templates
└── category.liquidURL Structure
Categories are scoped to a blog, so category pages are accessible at:
/blogs/:blogSlug/categories/:slug
For example: /blogs/news/categories/reviews, /blogs/news/categories/announcements
Each category record exposes a ready-built url property in exactly this
shape. Prefer linking with the url property rather than assembling the path
by hand, so links stay correct if the URL structure ever changes.
Template Variables
The category template receives these variables:
The category Object
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier |
title | string | Category name |
slug | string | URL-safe identifier |
description | string | Optional description shown at the top of the listing |
url | string | The category's archive page, e.g. /blogs/news/categories/reviews |
The posts Array
An array of all published posts in this category:
| Property | Type | Description |
|---|---|---|
posts | array | Posts belonging to this category |
Each post in the array has access to all standard post properties (title, description, publishDate, authors, image, etc.).
A post's own categories and tags are arrays of objects, not plain
strings. Each entry has a title and a slug — loop over them and read
category.title and category.slug. You do not need handleize; use
category.slug directly when building links.
Basic Template Example
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<div class="category-page">
<header class="category-header">
<h1>{{ category.title }}</h1>
<p class="post-count">{{ posts.size }} {% if posts.size == 1 %}post{% else %}posts{% endif %}</p>
</header>
<div class="posts-list">
{% if posts.size > 0 %}
{% for post in posts %}
<article class="post-card">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 400, height: 250 }}"
alt="{{ post.title }}"
loading="lazy"
>
{% endif %}
<div class="post-card__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 %}
</div>
</article>
{% endfor %}
{% else %}
<p class="no-posts">No posts in this category yet.</p>
{% endif %}
</div>
</div>
{% endcapture %}Working with Posts
Display Post Authors
{% for post in 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="author">
By {{ post.authors.first.name }}
</span>
{% endif %}
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%b %d, %Y' }}
</time>
{% endif %}
</div>
</article>
{% endfor %}Featured Image with Fallback
{% for post in posts %}
<article class="post-card">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 400, height: 250 }}"
alt="{{ post.title }}"
class="post-card__image"
loading="lazy"
>
{% elsif settings.global.fallbackImage %}
<img
src="{{ settings.global.fallbackImage | image_url: width: 400, height: 250 }}"
alt=""
class="post-card__image post-card__image--fallback"
loading="lazy"
>
{% endif %}
<h3>{{ post.title }}</h3>
</article>
{% endfor %}Posts Grouped by Month
{% assign current_month = '' %}
{% for post in 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 %}
<article class="post-item">
<a href="/posts/{{ post.slug }}">{{ post.title }}</a>
<time>{{ post.publishDate | date: '%d' }}</time>
</article>
{% if forloop.last %}</div>{% endif %}
{% endfor %}Complete Template Example
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<div class="category-page">
{# Breadcrumb navigation #}
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
<li aria-current="page">{{ category.title }}</li>
</ol>
</nav>
{# Category header #}
<header class="category-header">
<h1>{{ category.title }}</h1>
<p class="category-meta">
{{ posts.size }} {% if posts.size == 1 %}article{% else %}articles{% endif %}
</p>
</header>
{# Posts listing #}
{% if posts.size > 0 %}
<section class="category-posts">
{# Featured post (first/latest) #}
{% assign featured = posts.first %}
<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 }}"
>
</a>
{% endif %}
<div class="featured-post__content">
<h2>
<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">Read Article</a>
</div>
</article>
{# Remaining posts grid #}
{% if posts.size > 1 %}
<div class="post-grid">
{% for post in posts offset: 1 %}
<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">
<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: 100 }}
</p>
{% endif %}
</div>
</a>
</article>
{% endfor %}
</div>
{% endif %}
</section>
{% else %}
<div class="category-empty">
<h2>No Articles Yet</h2>
<p>There are no posts in the "{{ category.title }}" category yet. Check back soon!</p>
<a href="/blog" class="btn btn--secondary">Browse All Posts</a>
</div>
{% endif %}
{# Navigation #}
<nav class="category-nav">
<a href="/blog" class="back-link">
← Back to Blog
</a>
</nav>
</div>
{% endcapture %}
{% schema %}
{
"name": "category",
"settings": [
{
"type": "checkbox",
"name": "show_featured",
"label": "Feature Latest Post",
"defaultValue": true
},
{
"type": "select",
"name": "layout",
"label": "Posts Layout",
"options": [
{ "value": "grid", "label": "Grid" },
{ "value": "list", "label": "List" }
],
"defaultValue": "grid"
}
]
}
{% endschema %}Linking to Categories
From Post Templates
A post's categories are objects with title and slug. Build the archive URL
from the post's blog slug and the category slug — the same shape core generates:
{# In post.liquid template #}
{% if post.categories.size > 0 %}
<div class="post-categories">
{% for category in post.categories %}
<a href="/blogs/{{ post.blog.slug }}/categories/{{ category.slug }}" class="category-link">
{{ category.title }}
</a>
{% endfor %}
</div>
{% endif %}Category Navigation
When you have the full category records (for example via the blog's categories
list), each one carries a ready-built url, so you can link to it directly:
{# Display all categories #}
{% if blog.categories.size > 0 %}
<nav class="category-nav">
<h3>Categories</h3>
<ul>
{% for category in blog.categories %}
<li>
<a href="{{ category.url }}">{{ category.title }}</a>
</li>
{% endfor %}
</ul>
</nav>
{% endif %}Alternate Category Templates
Create variations for different category presentations:
templates/
├── category.liquid # Default category template
├── category.featured.liquid # Hero-style featured layout
├── category.compact.liquid # Compact list view
└── category.archive.liquid # Archive-style chronological