One Template. Every Interaction. Checked Before Deploy.
Build dynamic Python UIs without building a SPA.
Chirp is the hypermedia-native Python framework for server-rendered product UIs.
Typed route returns turn the same named template blocks into full pages, htmx
fragments, streaming HTML, and live SSE updates.chirp checkcatches broken
routes, blocks, and targets before users do.

from chirp import App, Page, Request
app = App()
@app.route("/search")
def search(request: Request):
query = request.query.get("q", "")
return Page("search.html", "results", query=query)
# Browser navigation -> full page
# htmx request -> just the "results" block
No SPA. No duplicated partials. No JavaScript build pipeline.
Why Build With Chirp
Use the same named template blocks for full pages, htmx fragments, OOB updates, deferred content, and SSE payloads—without maintaining parallel templates.
ReturnPage, Fragment, Suspense, or EventStream. Chirp handles content
negotiation and htmx awareness without manual response branching.
chirp checkvalidates routes, template blocks, htmx targets, OOB regions, and
SSE wiring before a broken interaction reaches production.
Send the shell first withSuspense, stream progressive HTML, or push rendered
fragments after load withEventStreamand SSE.
Build interactive product surfaces with Python, HTML, CSS, htmx, and browser-native features. Add Alpine.js or isolated islands only where local state earns its keep.
Designed for Python 3.14 and free-threading. Covered framework paths are exercised in free-threaded CI with explicit state and concurrency boundaries.
Where Chirp Fits
- Authenticated SaaS and internal tools where HTML is the product surface
- CRUD workflows that must work as plain forms and htmx-enhanced interactions
- Live dashboards, feeds, and operational consoles
- AI interfaces that stream tokens, tool activity, and rendered results
- Teams that want server-owned UI without duplicating page and partial templates
Chirp is deliberately focused. Choose an API-first framework when the primary product surface is JSON, or a batteries-included platform when you need a bundled ORM, generated admin, and its ecosystem. See When to Use Chirp and Non-Goals for the honest boundaries.
Return Values, Not Response Construction
Route functions return values that state what the browser needs:
return Page("search.html", "results", items=x) # Page or htmx fragment
return Fragment("cart.html", "count", count=n) # One named block
return Suspense("dashboard.html", stats=get_stats()) # Shell, then slow blocks
return EventStream(events()) # Post-load SSE updates
A dict still returns JSON. Use Responsewhen exact status, headers, or body
control is the right boundary. See the full
return-value reference for redirects, mutations, validation, and other cases.
A Small Python Foundation
Chirp uses Kida for block-aware rendering and Pounce as its ASGI server. They arrive as normal Python dependencies; you do not need to learn a larger ecosystem before building your first app. Read the ecosystem map when you want the implementation details.
Python-native. Free-threading ready. No npm required.