{% extends "blog/shell.html" %} {# ================================================================================ Blog List Template (Kida-Native) ================================================================================ Blog section index with featured posts, excerpts, and pagination. Extends blog/shell.html. KIDA FEATURES USED: - {% let %} for template-scoped variables - Optional chaining (?.) for null-safe access - Null coalescing (??) for smart defaults - Pipeline operator (|>) for filter chains - {% def %} for reusable post card components - {% match %} for conditional rendering CONTEXT VARIABLES: - section: Section object with blog posts - posts: List of blog post pages (may be paginated) - subsections: Blog categories/archives - total_pages: Total pagination pages - current_page: Current page number NOTE: Uses post.word_count and post.reading_time computed properties instead of filters for better performance (cached on first access). USAGE: Set `type: blog` in section _index.md ================================================================================ #} {% from 'partials/navigation-components.html' import pagination %} {% from 'partials/components/tags.html' import tag_list %} {% from 'partials/components/post-card.html' import post_card %} {# Category/subsection card #} {% def category_card(subsection) %} {% let sub_title = subsection?.title ?? 'Category' %} {% let sub_href = subsection?.href ?? subsection?._path ?? '#' %} {% let sub_desc = subsection?.metadata?.description ?? '' %} {% let sub_pages = subsection?.regular_pages ?? [] %} {% let index_page = subsection?.index_page %} {% let index_path = index_page?._path ?? '' %} {# Count non-index pages #} {% let content_pages = sub_pages |> rejectattr('relative_url', 'eq', index_path) |> list %} {% let page_count = content_pages | length %}

{{ sub_title }}

{% if sub_desc %}

{{ sub_desc }}

{% end %} {% if page_count > 0 %}

{{ page_count }} post{{ 's' if page_count != 1 else '' }}

{% end %}
{% end %} {# ============================================================================= MAIN TEMPLATE ============================================================================= #} {# Defensive defaults for pagination (coerce to int for comparisons) #} {% let total_pages = (total_pages ?? 1) | int %} {% let current_page = (current_page ?? 1) | int %} {% let total_posts = (total_posts ?? (posts | length if posts else 0)) | int %} {% let base_url = base_url ?? section?.href ?? section?._path ?? '/blog/' %} {% block blog_content %} {# Header - matches blog/about.html and blog/contact.html for consistent layout #} {% let section_title = section?.title ?? title ?? 'Blog' %} {% let section_desc = section?.metadata?.description ?? description ?? '' %}

{{ section_title }}

{% if section_desc %}

{{ section_desc }}

{% end %} {% if total_pages > 0 %}

Showing {{ posts | length }} of {{ total_posts }} posts {% if current_page > 1 %}(Page {{ current_page }} of {{ total_pages }}){% end %}

{% end %}
{% if posts %} {# Featured Posts Section (first page only) #} {% if current_page == 1 %} {% let featured_posts = posts |> where('featured', true) |> take(3) %} {% else %} {% let featured_posts = [] %} {% end %} {% if featured_posts | length > 0 %} {% end %} {# Regular Posts Section #} {% if current_page == 1 %} {% let regular_posts = posts |> where_not('featured', true) %} {% else %} {% let regular_posts = posts %} {% end %} {% if regular_posts %}
{% if featured_posts and current_page == 1 %}

Recent Posts

{% end %}
{% for post in regular_posts %} {{ post_card(post, variant='default') }} {% end %}
{% end %} {# Pagination #} {% if total_pages > 1 %} {{ pagination(current_page, total_pages, base_url) }} {% end %} {% elif subsections %} {# Show blog categories/archives if no posts #}

Categories

{% for subsection in subsections %} {{ category_card(subsection) }} {% end %}
{% else %} {# Empty State #}

No blog posts yet. Check back soon!

{% end %} {% end %}