Kida
)彡 Kida — Free-threading template engine for Python 3.14+ with AST compilation and modern syntax
Install / Use
/learn @lbliii/KidaREADME
)彡 Kida
A template engine that compiles to Python AST, renders to HTML/terminal/markdown, and scales across cores on free-threaded Python.
from kida import Environment
env = Environment()
template = env.from_string("Hello, {{ name }}!")
print(template.render(name="World"))
# Hello, World!
Why Kida
Most template engines generate Python source code as strings, then exec() it. Kida compiles directly to ast.Module — the same structured representation Python itself uses. This unlocks compile-time optimization, precise error mapping, and safe concurrent rendering that string-based engines can't achieve.
| | Kida | Jinja2 |
|---|---|---|
| Compilation target | Python AST (ast.Module) | Python source strings |
| Free-threading (PEP 703) | Safe under PYTHON_GIL=0 | Not tested/supported |
| Rendering modes | render(), render_stream(), render_block(), async variants | render(), generate() |
| Compile-time optimization | Constant folding, dead branch elimination, filter eval, component inlining | None |
| Terminal rendering | Built-in (autoescape="terminal") with 30+ ANSI-aware filters | None |
| Pattern matching | {% match %} / {% case %} | None |
| Null safety | ??, ?., ?|>, ?|, ??= | | default only |
| Components | {% def %} + {% slot %} + named slots | Macros (no slots) |
| Regions | {% region name(params) %} — parameterized blocks | None |
| Block rendering | render_block(), render_with_blocks() | None (third-party) |
| Fragment caching | {% cache "key" %} built-in | Extension required |
Performance
| Template complexity | Kida | vs Jinja2 |
|---|---|---|
| Minimal (~4µs) | Baseline | ~1x |
| Small loop + filter (~7µs) | Baseline | ~1x |
| Medium ~100 vars (~0.2ms) | Baseline | ~1.3x faster |
| Large 1000-item loop (~1.6ms) | Baseline | 2.5x faster |
| Complex 3-level inheritance (~19µs) | Baseline | 1.5x faster |
| With static_context (compile-time folding) | 1.5-2x additional speedup | N/A |
| Concurrent (2-4 cores, PYTHON_GIL=0) | Linear scaling | Not supported |
Installation
pip install kida-templates
Requires Python 3.14+. Zero runtime dependencies.
Render Anywhere
Kida renders to three surfaces from the same template syntax.
HTML (default)
from kida import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader("templates/"))
template = env.get_template("page.html")
html = template.render(title="Hello")
Terminal
from kida.terminal import terminal_env
env = terminal_env()
template = env.from_string("""
{{ "Deploy Status" | bold | cyan }}
{{ hr(40) }}
{% for svc in services %}
{{ svc.name | pad(20) }}{{ svc.status | badge }}
{% end %}
""")
print(template.render(services=[
{"name": "api", "status": "pass"},
{"name": "worker", "status": "fail"},
]))
30+ ANSI-aware filters (bold, fg(), pad, badge, bar, kv, table, tree, diff), built-in panel/box components, and LiveRenderer for in-place re-rendering with spinners.
Markdown
from kida.markdown import markdown_env
env = markdown_env()
template = env.from_string("# {{ title }}\n\n{{ body }}")
md = template.render(title="Report", body="All tests passed.")
Key Features
<details> <summary><strong>Template Inheritance</strong></summary>base.html:
<!DOCTYPE html>
<html>
<body>
{% block content %}{% end %}
</body>
</html>
page.html:
{% extends "base.html" %}
{% block content %}
<h1>{{ title }}</h1>
{% end %}
</details>
<details>
<summary><strong>Components & Named Slots</strong></summary>
{% def card(title) %}
<article class="card">
<h2>{{ title }}</h2>
<div class="actions">{% slot header_actions %}</div>
<div class="body">{% slot %}</div>
</article>
{% end %}
{% call card("Settings") %}
{% slot header_actions %}<button>Save</button>{% end %}
<p>Body content.</p>
{% end %}
</details>
<details>
<summary><strong>Pattern Matching & Null Safety</strong></summary>
{% match status %}
{% case "active" %}
Active user
{% case "pending" %}
Pending verification
{% case _ %}
Unknown status
{% end %}
{# Null coalescing #}
{{ user.nickname ?? user.name ?? "Anonymous" }}
{# Optional chaining #}
{{ config?.database?.host }}
{# Safe pipeline — stops on None #}
{{ data ?|> parse ?|> validate ?|> render }}
</details>
<details>
<summary><strong>Streaming & Block Rendering</strong></summary>
# Stream chunks as they render (chunked HTTP, SSE)
for chunk in template.render_stream(items=large_list):
response.write(chunk)
# Render a single block (HTMX partials)
html = template.render_block("content", title="Hello")
# Compose layouts with pre-rendered blocks
html = layout.render_with_blocks({"content": inner_html}, title="Page")
</details>
<details>
<summary><strong>Regions — Parameterized Blocks</strong></summary>
{% region sidebar(current_path="/") %}
<nav>{{ current_path }}</nav>
{% end %}
{{ sidebar(current_path="/about") }}
Regions are blocks (for render_block()) and callables (for inline use). Ideal for HTMX OOB swaps and framework integration.
# Pass static data at compile time — kida folds constants,
# eliminates dead branches, and evaluates pure filters
template = env.from_string(source, static_context={
"site": site_config,
"settings": app_settings,
})
# Only dynamic data needed at render time
html = template.render(page_title="Home", items=page_items)
67 pure filters evaluated at compile time. Dead {% if debug %} branches removed entirely. Component inlining for small defs with constant args.
Use kida render template.html --explain to see which optimizations are active.
All public APIs are safe under PYTHON_GIL=0 (Python 3.14t, PEP 703):
- Templates compile to immutable AST — no shared mutable state
- Rendering uses thread-local StringBuilder — no contention
- Environment uses copy-on-write for configuration changes
LiveRenderer.update()is thread-safe with internal locking
Module declares GIL independence via _Py_mod_gil = 0. Rendering scales linearly with cores.
Drop-in adapters for Flask, Starlette/FastAPI, and Django:
# Flask
from kida.contrib.flask import KidaFlask
kida = KidaFlask(app)
# Starlette / FastAPI
from kida.contrib.starlette import KidaStarlette
templates = KidaStarlette(directory="templates")
# Django
TEMPLATES = [{"BACKEND": "kida.contrib.django.KidaDjango", ...}]
</details>
GitHub Action — CI Reports
Turn pytest, coverage, ruff, and other tool output into formatted step summaries and PR comments.
- name: Run tests
run: pytest --junitxml=results.xml
- name: Post test report
uses: lbliii/kida@v0.3.2
with:
template: pytest
data: results.xml
data-format: junit-xml
Built-in templates
| Template | Data format | Tool |
|----------|-------------|------|
| pytest | junit-xml | pytest --junitxml |
| coverage | json | coverage.py --json or lcov |
| ruff | json | ruff --output-format json |
| ty | junit-xml | ty --output-format junit |
| jest | json | jest --json |
| gotest | junit-xml | go-junit-report |
| sarif | sarif | CodeQL, Semgrep, Trivy, ESLint |
PR comments with deduplication
- name: Post coverage to PR
uses: lbliii/kida@v0.3.2
with:
template: coverage
data: coverage.json
post-to: step-summary,pr-comment
Custom templates
- uses: lbliii/kida@v0.3.2
with:
template: .github/kida-templates/my-report.md
data: output.json
Inputs
| Input | Default | Description |
|-------|---------|-------------|
| template | (required) | Built-in name or path to template file |
| data | (required) | Path to data file |
| data-format | json | json, junit-xml, sarif, or lcov |
| post-to | step-summary | step-summary, pr-comment, or both |
| comment-header | template name | Marker for PR comment deduplication |
| token | github.token | GitHub token (needed for pr-comment) |
| python-version | 3.14 | Python version (skip to use existing) |
| install | true | Whether to pip install kida-templates |
CLI
# Render a template
kida render template.txt --data context.json
kida render dashboard.txt --mode terminal --width 80 --color truecolor
# Show which compiler optimizations are active
kida render template.html --explain
# Check all templates for syntax errors
kida check templates/
# Strict mode: require explicit end tags ({% endif %} not {% end %})
kida check templates/ --strict
# Validate macro call sites against signatures
kida check templates/ --validate-calls
# Accessibility and type checking
kida check templates/ --a11y --typed
# Auto-format templates
kida fmt templates/
API Reference
| Function | Description |
|----------|-------------|
| Environment() | Create a template environment |
| env.from_string(src) | Compile template from string |
| env.get_template(name) | Load template from filesystem |
| template.render(**ctx) | Full render (StringBuilder, fastest) |
| `template
Related Skills
node-connect
349.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
109.5kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
109.5kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
349.2kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
