Overview
Templateis the simplest return type: it renders a full HTML page from a kida template plus the context you pass it. Reach for it when a handler should return a complete page — a browser navigation, or any server-rendered view that isn't a fragment swap or a stream.
from chirp import Template
@app.route("/")
def index():
return Template("index.html", title="Home", items=get_items())
The first argument is the template path relative to your template_dir (default templates/). Every keyword argument becomes a variable in the template's render context.
When to reach for it
Templateis the base case the other return types build on. Learn this one first.
Template context
Every template automatically has access to:
- All keyword arguments passed to
Template(...). - Any globals registered with
@app.template_global()(see custom filters and globals). current_path(the request path, set torequest.path) — auto-injected when you don't pass it yourself.
Chirp does not put therequest object in the template context. To use request data in a template, take a typed Requestparameter and pass the values you need explicitly:
from chirp import Request, Template
@app.route("/dashboard")
def dashboard(request: Request):
return Template("dashboard.html", is_htmx=request.is_htmx)
@app.route("/users/{id:int}")
def user_profile(id: int):
user = get_user(id)
return Template("profile.html",
user=user,
posts=get_posts(user.id),
is_admin=user.role == "admin",
)
In profile.html:
<h1>{{ user.name }}</h1>
{% if is_admin %}
<span class="badge">Admin</span>
{% endif %}
{% for post in posts %}
<article>{{ post.title }}</article>
{% endfor %}
Composing a layout
A page template can pull shared chrome —<head>, nav, footer — from a base template. For standalone templates, kida supports {% extends %}inheritance:
{# base.html #}
<!DOCTYPE html>
<html>
<head><title>{% block title %}My App{% endblock %}</title></head>
<body>
<nav>{% block nav %}...{% endblock %}</nav>
<main>{% block content %}{% endblock %}</main>
</body>
</html>
{# page.html #}
{% extends "base.html" %}
{% block title %}{{ title }} - My App{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<p>{{ description }}</p>
{% endblock %}
Advanced: how kida renders
Chirp uses kida as its built-in template engine. The kidaEnvironmentis created during the app freeze phase and shared across every request handler.
- AST-native — kida compiles each template to an AST, then to a Python function.
- Block-aware — kida can render an individual named block, which is what makes
Fragmentrendering possible. - Streaming — kida supports generator-based rendering for progressive HTML.
- Thread-safe — compiled templates are immutable, so rendering is safe under free-threading.
You don't construct theEnvironmentyourself; Chirp builds and freezes it for you.