{% extends "blog/shell.html" %} {# ================================================================================ Blog Post Single Page Template (Kida-Native) ================================================================================ Individual blog post page optimized for reading. Extends blog/shell.html. FEATURES: - Featured image support - Author information and bio - Reading time estimation - Social sharing buttons - Related posts section - Comments integration point - Table of contents sidebar KIDA FEATURES USED: - {% let %} for template-scoped variables - Optional chaining (?.) for null-safe access - Null coalescing (??) for smart defaults - {% def %} for reusable components - {% match %} for conditional rendering NOTE: Uses page.word_count and page.reading_time computed properties instead of filters for better performance (cached on first access). USAGE: Set `type: blog` in frontmatter or use cascade from section ================================================================================ #} {% from 'partials/navigation-components.html' import page_navigation, toc as toc_macro %} {% from 'partials/series-nav.html' import series_nav %} {% from 'partials/components/tags.html' import tag_list %} {% from 'partials/components/post-card.html' import post_card %} {% from 'partials/components/author-bio.html' import author_bio %} {% from 'partials/components/blog-share-dropdown.html' import blog_share_dropdown %} {% from 'partials/components/related-posts.html' import related_posts %} {% from 'partials/components/comments-section.html' import comments_section %} {% from 'partials/components/blog-post-meta.html' import blog_post_meta %} {% from 'partials/components/newsletter-cta.html' import newsletter_cta %} {# ============================================================================= MAIN TEMPLATE ============================================================================= #} {% block blog_content %} {# Template-scoped variables with null-safe access #} {% let page_title = page?.title ?? 'Blog Post' %} {% let page_date = page?.date %} {% let page_word_count = page?.word_count ?? 0 %} {% let page_read_time = page?.reading_time ?? 0 %} {% let page_tags = page?.tags ?? [] %} {% let page_href = (page?.href ?? page?._path ?? '') | absolute_url %} {% let theme_features = theme?.features ?? [] %} {# Params with null-safe access #} {% let post_image = params?.image ?? params?.cover ?? '' %} {% let post_desc = params?.description ?? '' %} {% let post_updated = params?.updated %} {# Author: resolve from data/authors.yml by slug, fall back to inline params #} {% let author_slug = params?.author ?? '' %} {% let authors_registry = site?.data?.authors ?? {} %} {% let author_data = authors_registry.get(author_slug, {}) if author_slug else {} %} {% let post_author = author_data?.name ?? params?.author ?? '' %} {% let post_author_avatar = author_data?.avatar ?? params?.author_avatar ?? '' %} {% let post_author_title = author_data?.title ?? author_data?.company ?? params?.author_title ?? '' %} {% let post_author_bio = author_data?.bio ?? params?.author_bio ?? '' %} {% let post_author_links = author_data?.links ?? params?.author_links ?? [] %} {% let post_views = params?.views %} {% let css_class = params?.css_class ?? '' %} {% let show_newsletter = params?.show_newsletter ?? false %} {% let show_comments = params?.comments ?? true %} {% let comments_provider = params?.comments_provider ?? '' %} {# Two-column layout like docs/single: content | TOC. Content gets 1fr, TOC fixed. #} {# Use div not main - base.html already provides main#main-content (nested main is invalid) #} {% let toc_items_list = toc_items ?? [] %} {% let show_toc = page.toc and (toc_items_list | length >= 3) %}
{# Top row: Share in top right (like docs, no breadcrumbs) #}
{{ blog_share_dropdown(page, page_href) }}
{# Featured Image (blog-specific) #} {% if post_image %}
{{ page_title }}
{% end %}

{{ page_title }}

{% if post_desc %}

{{ post_desc }}

{% end %} {# Post Metadata: date, reading time, updated, views + mini author card #}
{{ blog_post_meta(post_author, post_author_avatar, post_author_title, page_date, page_read_time, post_views, 'content.author' in theme_features, page_word_count and 'content.reading_time' in theme_features, post_updated) }}
{# Main Post Content #}
{{ content | safe }}
{# Post Footer: tags, author bio, prev/next #}
{# Tags - moved after content #} {% if page_tags | length > 0 %} {% end %} {# Author Bio #} {% if 'content.author' in theme_features %} {{ author_bio(post_author, post_author_avatar, post_author_title, post_author_bio, post_author_links) }} {% end %} {# Series nav: show series name and part when in a series #} {{ series_nav(page) }} {# Prev/Next - inside content column so it aligns with prose when TOC is present #} {{ page_navigation(page) }}
{% block blog_after_content %}{% end %} {# Right Sidebar: TOC - only show when 3+ headings (avoids clutter on short posts) #} {# Uses same enhanced TOC as docs: scroll highlighting, count badges, collapsible groups (no TOC progress bar - page has global reading-progress) #} {% if show_toc %} {% end %}
{% end %} {% block blog_after_content %}
{{ related_posts(page?.related_posts ?? []) }} {{ comments_section(comments_provider if show_comments else '') }}
{% end %}