ワンクリックで
kida-jinja2-migration
Convert Jinja2 templates to Kida syntax. Use when migrating from Jinja2, Django templates, or similar engines.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Convert Jinja2 templates to Kida syntax. Use when migrating from Jinja2, Django templates, or similar engines.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use Kida with Chirp for HTMX partials, fragment rendering, block validation. Use when building Chirp web apps.
Write correct Kida templates from scratch. Use when creating templates, writing views, or authoring template content.
Use Kida with Bengal SSG: block caching, incremental builds, template context. Use when building Bengal sites or optimizing build performance.
Add custom Kida filters with proper type coercion. Use when adding filters, extending templates, or handling YAML/config int/str.
Understand Kida expression behavior: `+` operator, list vs string, export accumulation. Use when debugging unexpected output or expression behavior.
Use Kida static analysis for pre-render validation, incremental builds, block caching. Use when validating template context, optimizing build times, or implementing caching.
| name | kida-jinja2-migration |
| description | Convert Jinja2 templates to Kida syntax. Use when migrating from Jinja2, Django templates, or similar engines. |
Kida is not a drop-in replacement. Templates must be rewritten. This skill guides the conversion.
{% end %}Jinja2 uses tag-specific endings. Kida uses one:
| Jinja2 | Kida |
|---|---|
{% endif %} | {% end %} |
{% endfor %} | {% end %} |
{% endblock %} | {% end %} |
{% macro name(...) %} | {% def name(...) %} (Kida has no {% macro %} keyword) |
{% endmacro %} | {% end %} |
{% if condition %}...{% end %}
{% for item in items %}...{% end %}
{% block content %}...{% end %}
# Before (Jinja2)
from jinja2 import Environment, FileSystemLoader
from markupsafe import Markup
# After (Kida)
from kida import Environment, FileSystemLoader, Markup
# Jinja2
env.filters['money'] = format_money
env.tests['prime'] = is_prime
# Kida
env.add_filter('money', format_money)
env.add_test('prime', is_prime)
{% let %}, {% set %}, {% export %}| Keyword | Scope |
|---|---|
{% let x = ... %} | Template-wide (like Jinja2's set) |
{% set x = ... %} | Block-scoped — does not leak out of {% if %}, {% for %}, etc. |
{% export x = ... %} | Promotes variable to template (outermost) scope; escapes multiple nested blocks |
⚠ Key difference from Jinja2: In Jinja2,
{% set %}inside{% if %}modifies the outer variable. In Kida,{% set %}is block-scoped — the value stays inside the block. Use{% let %}for template-wide variables, or{% export %}to push a value out of a block into the template scope (it can cross multiple nested blocks).{# Kida: set is block-scoped #} {% let name = "outer" %} {% if true %} {% set name = "inner" %} {# does NOT change the outer 'name' #} {% end %} {{ name }} → outer {# To modify outer scope from inside a block, use export: #} {% if true %} {% export name = "inner" %} {% end %} {{ name }} → inner
|>Kida adds |> for left-to-right filter chains. Both | and |> work:
{{ title |> escape |> upper |> truncate(50) }}
{% match %}Replace chained {% if %}/{% elif %} with {% match %}:
{% match status %}
{% case "active" %}<span class="green">Active</span>
{% case "pending" %}<span class="yellow">Pending</span>
{% case _ %}<span>Unknown</span>
{% end %}
Kida raises UndefinedError for any undefined variable — it never silently returns an empty
string like Jinja2. This is the default and cannot be disabled.
{# This raises UndefinedError if 'nickname' is not in the context #}
{{ nickname }}
{# Use | default() for optional values #}
{{ nickname | default("Anonymous") }}
{# Use 'is defined' test for conditional logic #}
{% if nickname is defined %}
Hello, {{ nickname }}
{% end %}
Migration tip: Audit every variable in your Jinja2 templates. Any variable that might not be passed to
render()needs| default(...)or anis definedguard.
{% cache key %}...{% end %} — Built-in block caching{% async for %}, {{ await expr }}template.render_stream() for HTMX/SSEnamespace() SupportJinja2's namespace() object does not exist in Kida. Use the scoping keywords instead:
| Jinja2 pattern | Kida equivalent |
|---|---|
{% set ns = namespace(count=0) %} | {% let count = 0 %} |
{% set ns.count = ns.count + 1 %} (inside loop) | {% export count = count + 1 %} |
format Filter Uses str.format()The format filter uses Python's str.format() with {} placeholders — not %-style:
{# Correct — str.format() style #}
{{ "Hello, {}!" | format(name) }}
{{ "{:.2f}" | format(price) }}
{# WRONG — %-style will raise an error #}
{{ "%.2f" | format(price) }}
For numeric formatting, prefer the dedicated filters:
{{ price | decimal(2) }} → 19.99
{{ amount | format_number(2) }} → 1,234.57
| Error | Fix |
|---|---|
ImportError: Markup from markupsafe | Import Markup from kida |
FilterRegistry does not support item assignment | Use env.add_filter(name, func) |
Unexpected tag 'endif' | Use {% end %} not {% endif %} |
UndefinedError: Undefined variable 'varname' in <template>:<line> | Add ` |
format filter uses str.format() | Use {} placeholders, not %s/%.2f |
Unknown icon 'arrow' | Use directional variant: icons.arrow_r, arrow_l, arrow_u, arrow_d |
Variable doesn't update outside {% if %} | {% set %} is block-scoped — use {% let %} or {% export %} |
template = env.from_string("Hello, {{ name }}!")
assert template.render(name="World") == "Hello, World!"