Layout Patterns

Block-heavy layouts, boost pattern, and composition

2 min read 393 words

Overview

Chirp templates use Kida's block system:{% extends %}, {% block %}, {% include %}, and {% call %}. This guide covers patterns for block-heavy layouts and when to use each construct.

Boost Layout

Thechirp/layouts/boost.htmllayout is the recommended base for htmx-boost + SSE apps:

{% extends "chirp/layouts/boost.html" %}
{% block title %}My App{% end %}
{% block content %}
  <p>Page content goes here.</p>
{% end %}
{% block body_after %}
  <script>/* app-specific JS */</script>
{% end %}

Structure:

  • #main— htmx-boost target; gets replaced on navigation
  • body_before — above #main(e.g. nav bar)
  • content — inside #main; page-specific HTML
  • sse_scopeoutside #main; SSE connections persist across navigations
  • body_after— scripts, analytics

Important: Putsse_scope outside #main. If it's inside content, it gets replaced on navigation and live updates stop.

Outer vs Inner Content

For SSE swap targets and fragment structure:

  • Outer element — Thesse-swaptarget. Holds padding, border, layout. Stays in the DOM; its innerHTML is replaced.
  • Inner element — The fragment block content. No duplicate padding or border.
<!-- Outer: swap target, has padding/border; hx-target="this" when sse-connect has hx-disinherit -->
<div class="answer" sse-swap="answer" hx-target="this">
  <!-- Inner: fragment renders this; no extra padding -->
  <div class="answer-body" data-copy-text="...">
    <div class="answer-content prose">...</div>
    <button class="copy-btn">Copy</button>
  </div>
</div>

Avoid nesting two elements with the same padding/border — it causes double spacing. Keep .copy-btn in normal flow (no position: absolute) so it stays with its answer.

When to Use Each Construct

Construct Use for
{% extends %} Base layout (boost, custom shell). One per template.
{% block %} Overridable sections. Child templates fill or extend.
{% include %} Reusable partials (headers, footers, cards). No block params.
{% call %} Macros with parameters. Use with{% def %}.

Blocks define slots; includes pull in full partials; call/def are parameterized components.

Block Inheritance

Child templates override blocks by redefining them:

{% extends "base.html" %}
{% block content %}
  {{ super() }}
  <p>Additional content after parent block.</p>
{% end %}

{{ super() }}renders the parent block's content. Omit it to replace entirely.

Next Steps

  • Fragments — Block-level rendering for htmx
  • RAG Demo — Full layout example with SSE