Post template
Reference for the post object passed to post templates
The post template renders individual blog posts or news articles. It displays the full post content, author information, categories, and related metadata.
Location
└── theme
└── templates
└── post.liquidThe post Object
The post template has access to the post object with these properties:
Core Properties
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier |
title | string | Post title |
description | string | Post excerpt/lede |
slug | string | URL-safe identifier |
image | media | Featured image |
Publishing Properties
| Property | Type | Description |
|---|---|---|
publishDate | string | Publication date (ISO 8601) |
blog | blog | Parent blog |
Authors & Taxonomy
| Property | Type | Description |
|---|---|---|
authors | array | Post authors (people) |
categories | array | Post categories |
tags | array | Post tags |
Content
| Property | Type | Description |
|---|---|---|
blocks | array | Content blocks |
customAttributes | object | Custom attribute values |
theme | object | Theme-specific field values |
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
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<article class="post">
<header class="post-header">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 1200, height: 600 }}"
alt="{{ post.image.alt | default: post.title }}"
class="post-header__image"
>
{% endif %}
<h1>{{ post.title }}</h1>
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%B %d, %Y' }}
</time>
{% endif %}
{% if post.description %}
<p class="lead">{{ post.description }}</p>
{% endif %}
</header>
<div class="post-body">
{% stageblocks post %}
</div>
</article>
{% endcapture %}Working with Authors
Single Author Display
{% if post.authors.size > 0 %}
{% assign author = post.authors.first %}
<div class="post-author">
{% if author.image %}
<img
src="{{ author.image | image_url: width: 80, height: 80 }}"
alt="{{ author.name }}"
class="author-avatar"
>
{% endif %}
<div class="author-info">
<span class="author-name">
<a href="/people/{{ author.slug }}">{{ author.name }}</a>
</span>
{% if author.role %}
<span class="author-role">{{ author.role }}</span>
{% endif %}
</div>
</div>
{% endif %}Multiple Authors
{% if post.authors.size > 0 %}
<div class="post-authors">
<span class="byline">By</span>
{% for author in post.authors %}
<a href="/people/{{ author.slug }}">{{ author.name }}</a>
{% unless forloop.last %}
{% if forloop.index == post.authors.size | minus: 1 %}
and
{% else %}
,
{% endif %}
{% endunless %}
{% endfor %}
</div>
{% endif %}Author Bio Box
{% if post.authors.size > 0 %}
<aside class="author-box">
<h3>About the Author{% if post.authors.size > 1 %}s{% endif %}</h3>
{% for author in post.authors %}
<div class="author-bio">
{% if author.image %}
<img
src="{{ author.image | image_url: width: 120, height: 120 }}"
alt="{{ author.name }}"
>
{% endif %}
<div>
<h4>{{ author.name }}</h4>
{% if author.role %}
<p class="role">{{ author.role }}</p>
{% endif %}
{% if author.biography_html %}
{{ author.biography_html }}
{% endif %}
</div>
</div>
{% endfor %}
</aside>
{% endif %}Working with Categories and Tags
Display Categories
{% if post.categories.size > 0 %}
<div class="post-categories">
{% for category in post.categories %}
<a href="/blog?category={{ category | handleize }}" class="category-badge">
{{ category }}
</a>
{% endfor %}
</div>
{% endif %}Display Tags
{% if post.tags.size > 0 %}
<div class="post-tags">
<span class="tags-label">Tags:</span>
{% for tag in post.tags %}
<a href="/blog?tag={{ tag | handleize }}" class="tag">
{{ tag }}
</a>
{% unless forloop.last %}, {% endunless %}
{% endfor %}
</div>
{% endif %}Combined Taxonomy
<footer class="post-meta">
{% if post.categories.size > 0 %}
<div class="meta-item">
<strong>Categories:</strong>
{% for category in post.categories %}
<a href="/blog?category={{ category | handleize }}">{{ category }}</a>
{% unless forloop.last %}, {% endunless %}
{% endfor %}
</div>
{% endif %}
{% if post.tags.size > 0 %}
<div class="meta-item">
<strong>Tags:</strong>
{% for tag in post.tags %}
<a href="/blog?tag={{ tag | handleize }}">{{ tag }}</a>
{% unless forloop.last %}, {% endunless %}
{% endfor %}
</div>
{% endif %}
</footer>Working with the Blog Relationship
Back to Blog Link
{% if post.blog %}
<a href="/blogs/{{ post.blog.slug }}" class="back-link">
← Back to {{ post.blog.title }}
</a>
{% endif %}Breadcrumb with Blog
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
{% if post.blog %}
<li><a href="/blogs/{{ post.blog.slug }}">{{ post.blog.title }}</a></li>
{% endif %}
<li aria-current="page">{{ post.title }}</li>
</ol>
</nav>Working with Theme-Specific Fields
Access custom fields defined in the template schema via post.theme:
{# Template schema defines: reading_time, show_social_share, related_posts #}
{% if post.theme.reading_time %}
<span class="reading-time">{{ post.theme.reading_time }} min read</span>
{% endif %}
{% if post.theme.show_social_share %}
{% render 'snippets/social-share' title: post.title %}
{% endif %}Complete Template Example
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<article class="post-page">
{# Breadcrumb #}
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
{% if post.blog %}
<li><a href="/blogs/{{ post.blog.slug }}">{{ post.blog.title }}</a></li>
{% endif %}
<li aria-current="page">{{ post.title }}</li>
</ol>
</nav>
{# Post header #}
<header class="post-header">
{% if post.categories.size > 0 %}
<div class="post-categories">
{% for category in post.categories %}
<a href="/blog?category={{ category | handleize }}" class="category-badge">
{{ category }}
</a>
{% endfor %}
</div>
{% endif %}
<h1 class="post-title">{{ post.title }}</h1>
<div class="post-meta">
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%B %d, %Y' }}
</time>
{% endif %}
{% if post.theme.reading_time %}
<span class="reading-time">{{ post.theme.reading_time }} min read</span>
{% endif %}
</div>
{# Authors #}
{% if post.authors.size > 0 %}
<div class="post-authors">
{% for author in post.authors %}
<a href="/people/{{ author.slug }}" class="author">
{% if author.image %}
<img
src="{{ author.image | image_url: width: 48, height: 48 }}"
alt="{{ author.name }}"
class="author-avatar"
>
{% endif %}
<span class="author-name">{{ author.name }}</span>
</a>
{% endfor %}
</div>
{% endif %}
</header>
{# Featured image #}
{% if post.image %}
<figure class="post-featured-image">
<img
src="{{ post.image | image_url: width: 1200, height: 600 }}"
alt="{{ post.image.alt | default: post.title }}"
>
{% if post.image.caption %}
<figcaption>{{ post.image.caption }}</figcaption>
{% endif %}
</figure>
{% endif %}
{# Post content #}
<div class="post-content">
{% if post.description %}
<p class="lead">{{ post.description }}</p>
{% endif %}
{% stageblocks post %}
</div>
{# Tags #}
{% if post.tags.size > 0 %}
<footer class="post-footer">
<div class="post-tags">
<span class="tags-label">Tagged:</span>
{% for tag in post.tags %}
<a href="/blog?tag={{ tag | handleize }}" class="tag">{{ tag }}</a>
{% endfor %}
</div>
</footer>
{% endif %}
{# Social sharing #}
{% if post.theme.show_social_share != false %}
<div class="post-share">
<h3>Share this post</h3>
{% render 'snippets/social-share' title: post.title %}
</div>
{% endif %}
{# Author bio #}
{% if post.authors.size > 0 %}
<aside class="author-bio-section">
{% for author in post.authors %}
<div class="author-bio">
{% if author.image %}
<img
src="{{ author.image | image_url: width: 120, height: 120 }}"
alt="{{ author.name }}"
class="author-bio__image"
>
{% endif %}
<div class="author-bio__content">
<h4>
<a href="/people/{{ author.slug }}">{{ author.name }}</a>
</h4>
{% if author.role %}
<p class="author-role">{{ author.role }}</p>
{% endif %}
{% if author.biography_html %}
<div class="author-bio__text">{{ author.biography_html }}</div>
{% endif %}
</div>
</div>
{% endfor %}
</aside>
{% endif %}
{# Navigation #}
<nav class="post-nav">
{% if post.blog %}
<a href="/blogs/{{ post.blog.slug }}" class="back-link">
← More from {{ post.blog.title }}
</a>
{% endif %}
</nav>
</article>
{% endcapture %}
{% schema %}
{
"name": "post",
"settings": [
{
"type": "number",
"name": "reading_time",
"label": "Reading Time (minutes)"
},
{
"type": "checkbox",
"name": "show_social_share",
"label": "Show Social Share Buttons",
"defaultValue": true
},
{
"type": "checkbox",
"name": "show_author_bio",
"label": "Show Author Bio",
"defaultValue": true
}
],
"blocks": [
"content",
"image-gallery",
"video-gallery",
"well"
]
}
{% endschema %}Using Posts in Components
Create a reusable post card component:
{# components/post-card.liquid #}
{#
Required: post (post object)
Optional: show_excerpt (boolean), show_author (boolean)
#}
{% assign show_excerpt = show_excerpt | default: true %}
{% assign show_author = show_author | default: false %}
<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>
{% if show_excerpt and post.description %}
<p class="post-card__excerpt">{{ post.description | truncate: 120 }}</p>
{% endif %}
<div class="post-card__meta">
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%b %d, %Y' }}
</time>
{% endif %}
{% if show_author and post.authors.size > 0 %}
<span class="post-card__author">
by {{ post.authors.first.name }}
</span>
{% endif %}
</div>
</div>
</a>
</article>Usage:
<div class="post-grid">
{% for post in all_posts limit: 6 %}
{% render 'components/post-card' post: post, show_author: true %}
{% endfor %}
</div>Alternate Post Templates
Create variations for different post types:
templates/
├── post.liquid # Default blog post template
├── post.news.liquid # News article layout
├── post.review.liquid # Review with rating
└── post.interview.liquid # Interview Q&A formatAlternate templates appear in the CMS for editors to select per post.