Chirp
A Python web framework for HTMX, HTML fragments, streaming HTML, and Server-Sent Events
Python Web Framework for HTML Over the Wire
HTMX. Fragments. Streaming. Server-Sent Events.
Chirp is a Python web framework built from scratch for HTML-over-the-wire applications. It serves full pages, fragments, streams, and real-time events through its built-in template engine, kida.
from chirp import App, Template
app = App()
@app.route("/")
def index():
return Template("index.html", title="Home")
app.run()
Why Use Chirp
Render named template blocks independently. Full page on navigation, just the fragment on htmx requests. Same template, same data, different scope.
Send the page shell first, then fill in content as data arrives. Progressive rendering over chunked transfer.
Push kida-rendered HTML fragments to the browser in real time. Combined with htmx, this enables live UI updates with zero client-side JavaScript.
app.check() validates every hx-get, hx-post, and actionagainst the route table at startup. Broken references become compile-time errors, not runtime 404s.
Designed for Python 3.14t from the first line. Frozen config, frozen requests, ContextVar isolation, immutable data structures. Data races are structurally impossible.
Same author, no seam. Fragment rendering, streaming templates, and filter registration are first-class features.
Common Use Cases
- Building HTMX-driven apps without a SPA frontend
- Serving server-rendered pages and HTML fragments from the same templates
- Streaming HTML for dashboards, feeds, and AI responses
- Delivering real-time updates with Server-Sent Events
- Using browser-native UI features instead of framework-heavy client state
Return Values, Not Response Construction
Route functions return values. The framework handles content negotiation based on the type:
return "Hello" # -> 200, text/html
return {"users": [...]} # -> 200, application/json
return Template("page.html", title="Home") # -> 200, rendered via kida
return Fragment("page.html", "results", items=x) # -> 200, rendered block
return Stream("dashboard.html", **async_ctx) # -> 200, streamed HTML
return EventStream(generator()) # -> SSE stream
return Response(body=b"...", status=201) # -> explicit control
return Redirect("/login") # -> 302
No make_response(). No jsonify(). The type is the intent.
The Bengal Ecosystem
A structured reactive stack — every layer written in pure Python for 3.14t free-threading.
| ᓚᘏᗢ | Bengal | Static site generator | Docs |
| ∿∿ | Purr | Content runtime | — |
| ⌁⌁ | Chirp | Web framework ← You are here | Docs |
| =^..^= | Pounce | ASGI server | Docs |
| )彡 | Kida | Template engine | Docs |
| ฅᨐฅ | Patitas | Markdown parser | Docs |
| ⌾⌾⌾ | Rosettes | Syntax highlighter | Docs |
Python-native. Free-threading ready. No npm required.