Kida Integration

How Chirp reads a template's structure from Kida to discover OOB regions, validate blocks, and build layout contracts

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

Kida is Chirp's template engine. At build time it hands Chirp the structure of each template — its block names, its regions, and which context keys each block reads. Chirp reads that structure instead of hard-coding which blocks exist, which is how fragment rendering, out-of-band (OOB) regions, and layout contracts work with no framework-specific config.

You rarely touch any of this directly. To add an OOB region you write a {% region name_oob(...) %}block in your layout and register its DOM target; Chirp discovers the rest. This page explains that discovery so you can add your own regions and reason about what gets rendered.

Add an OOB region

An OOB region is a layout block whose name ends in_oob. Chirp finds every such block, renders it as an out-of-band swap on boosted navigation, and targets it at a DOM element by id. Adding one is two steps.

  1. 1

    Write the region in your layout

    A{% region name(...) %}block compiles to two things at once: a named block Chirp can render in isolation, and a callable you invoke from a shell slot. Name it with the_oobsuffix so discovery picks it up.

    {% region sidebar_oob(current_path="/") %}
      {{ sidebar(current_path=current_path) }}
    {% end %}
    
  2. 2

    Register its DOM target

    Tell Chirp which element id the region replaces:

    app.register_oob_region("sidebar_oob", target_id="sidebar-nav")
    

    If you skip registration, Chirp falls back to a convention: it strips the _oob suffix, sosidebar_oob targets the element with id="sidebar". Register explicitly when the id does not match that convention.

That's the whole task. The OOB registry page documents register_oob_region options (swap, wrap, optional) and the fail-loud policy in full.

ChirpUI registers three regions for you when you load its app shell — breadcrumbs_oob, sidebar_oob, and title_oob, mapped to chirpui-topbar-breadcrumbs, chirpui-sidebar-nav, and chirpui-document-title. See App Shells for regions in practice.

Why regions beat plain blocks

Kida's{% region %}compiles to BOTH a renderable block (for OOB updates) and a callable (for{{ name(args) }}in shell slots). One definition serves both, so you don't duplicate the markup:

  • Renderable — Chirp renders the block on its own for an OOB swap.
  • Callable — you invoke{{ sidebar_oob(current_path=...) }}inside a slot.
  • Parameterized{% region sidebar_oob(current_path="/") %}makes the region self-contained; the same defaults apply whether it renders as a slot or as an OOB update.

Theexamples/chirpui/shell_oobreference layout defines and calls a region in one place:

{% region breadcrumbs_oob(breadcrumb_items=[{"label":"Home","href":"/"}]) %}
{{ breadcrumbs(breadcrumb_items) }}
{% end %}

Source: examples/chirpui/shell_oob/pages/_layout.html.

{% call app_shell(brand="Settings Console", sidebar_collapsible=true, brand_boost=true) %}
  {% slot topbar %}
  {{ breadcrumbs_oob(breadcrumb_items=breadcrumb_items ?? [{"label":"Home","href":"/"}]) }}
  {% end %}

Source: examples/chirpui/shell_oob/pages/_layout.html.

Migrate a block to a region

If your layout uses a plain{% block name_oob %}and duplicates the same markup in a shell slot, collapse it to a single region.

{% block breadcrumbs_oob %}
  {{ breadcrumbs(breadcrumb_items) }}
{% end %}

{% call app_shell() %}
  {% slot topbar %}
    {{ breadcrumbs(breadcrumb_items) }}  {# duplicated #}
  {% end %}
{% end %}

The OOB block and the slot render the same content from two copies. They drift.

{% region breadcrumbs_oob(breadcrumb_items=[{"label":"Home","href":"/"}]) %}
  {{ breadcrumbs(breadcrumb_items) }}
{% end %}

{% call app_shell() %}
  {% slot topbar %}
    {{ breadcrumbs_oob(breadcrumb_items=breadcrumb_items ?? [{"label":"Home","href":"/"}]) }}
  {% end %}
{% end %}

One definition; the slot calls the region. No duplication, no drift.

Then remove any empty_page_layoutblock overrides you added to suppress the OOB block on full-page renders — Chirp already suppresses OOB output on full-page responses through its block overrides, so those workarounds are no longer needed.

How discovery and validation work

Most readers stop above. The rest of this page is the mechanism for the curious.