Chirp

A Python web framework for the modern web platform

HTML Over the Wire

Fragments. Streaming. SSE. Free-threading native.

Chirp is a Python web framework built from scratch for the modern web platform. It serves HTML beautifully -- full pages, fragments, streams, and real-time events -- all 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 Chirp?

Fragment Rendering

Render named template blocks independently. Full page on navigation, just the fragment on htmx requests. Same template, same data, different scope.

Streaming HTML

Send the page shell immediately, fill in content as data arrives. Progressive rendering over chunked transfer -- no loading spinners, no skeleton screens.

Server-Sent Events

Push kida-rendered HTML fragments to the browser in real-time. Combined with htmx, this enables live UI updates with zero client-side JavaScript.

Typed Contracts

app.check() validates every hx-get, hx-post, and actionagainst the route table at startup. Broken references become compile-time errors, not runtime 404s.

Free-Threading Native

Designed for Python 3.14t from the first line. Frozen config, frozen requests, ContextVar isolation, immutable data structures. Data races are structurally impossible.

Kida Built In

Same author, no seam. Fragment rendering, streaming templates, and filter registration are first-class features -- not afterthoughts bolted on via extensions.


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

purr        Content runtime   (connects everything)
pounce      ASGI server       (serves apps)
⌁⌁ chirp       Web framework     (serves HTML) ← You are here
kida        Template engine   (renders HTML)
patitas     Markdown parser   (parses content)
rosettes    Syntax highlighter (highlights code)
bengal      Static site gen   (builds sites)