https://github.com/lbliii/chirp
⌁⌁ Chirp — HTML-first web framework for Python 3.14+ with streaming, SSE, and fragment rendering
https://github.com/lbliii/chirp
asgi free-threading html-over-the-wire htmx kida nogil python python314 sse streaming web-framework
Last synced: 12 days ago
JSON representation
⌁⌁ Chirp — HTML-first web framework for Python 3.14+ with streaming, SSE, and fragment rendering
- Host: GitHub
- URL: https://github.com/lbliii/chirp
- Owner: lbliii
- License: mit
- Created: 2026-02-07T16:56:19.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-03-04T03:27:06.000Z (19 days ago)
- Last Synced: 2026-03-04T05:39:09.597Z (19 days ago)
- Topics: asgi, free-threading, html-over-the-wire, htmx, kida, nogil, python, python314, sse, streaming, web-framework
- Language: Python
- Homepage: https://lbliii.github.io/chirp/
- Size: 1.85 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Roadmap: ROADMAP.md
Awesome Lists containing this project
- awesome-python-web-frameworks - Chirp - a Python ASGI web framework for HTML over the wire, streaming responses, and Server-Sent Events. (Micro-frameworks / Async)
README
# ⌁⌁ Chirp
[](https://pypi.org/project/bengal-chirp/)
[](https://pypi.org/project/bengal-chirp/)
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/bengal-chirp/)
**A Python web framework for HTML over the wire.**
```python
from chirp import App
app = App()
@app.route("/")
def index():
return "Hello, World!"
app.run()
```
---
## What is Chirp?
Chirp is a Python web framework built for the modern web platform: browser-native UI, HTML over the wire, streaming responses, and Server-Sent Events. Use plain Kida templates, your own CSS, or optional companion packages like `chirp-ui`. Return values drive content negotiation — no `make_response()`, no `jsonify()`. The type *is* the intent.
**What's good about it:**
- **Browser-native UI** — ``, `popover`, View Transitions, container queries. Most of what required a JS framework is now native HTML and CSS.
- **HTML over the wire** — Serve full pages, template fragments, streaming HTML, and SSE. Built for htmx and the modern browser.
- **Streaming HTML** — Send the page shell immediately and fill in content as data becomes available. No loading spinners, no skeleton screens.
- **Server-Sent Events** — Push real-time updates over plain HTTP. No WebSocket protocol upgrade, no special infrastructure.
---
## Installation
```bash
# pip
pip install bengal-chirp
# uv
uv add bengal-chirp
```
Requires Python 3.14+.
Chirp works on its own with plain templates. `chirp-ui` is an optional companion UI layer, not part of the framework core.
---
## Quick Start
```bash
chirp new myapp && cd myapp && python app.py
```
| Function | Description |
|----------|-------------|
| `chirp new ` | Scaffold an auth-ready project |
| `chirp new --shell` | Scaffold with a persistent app shell (topbar + sidebar) |
| `chirp new --sse` | Scaffold with SSE boilerplate (`EventStream`, `sse_scope`) |
| `chirp run ` | Start the dev server from an import string |
| `chirp check ` | Validate hypermedia contracts |
| `chirp check --warnings-as-errors` | Fail CI on contract warnings |
| `chirp routes ` | Print the registered route table |
| `App()` | Create an application |
| `@app.route(path)` | Register a route handler |
| `Template(name, **ctx)` | Render a full template |
| `Template.inline(src, **ctx)` | Render from string (prototyping) |
| `Page(name, block, **ctx)` | Auto Fragment or Template based on request |
| `PageComposition(template, fragment_block, ...)` | Python-first composition with regions |
| `Fragment(name, block, **ctx)` | Render a named template block |
| `Stream(name, **ctx)` | Stream HTML progressively |
| `Suspense(name, **ctx)` | Shell first, OOB swaps for deferred data |
| `EventStream(gen)` | Server-Sent Events stream |
| `hx_redirect(url)` | Redirect helper for htmx and full-page requests |
| `app.run()` | Start the development server |
---
## Features
| Feature | Description | Docs |
|---------|-------------|------|
| **Routing** | Pattern matching, path params, method dispatch | [Routing →](https://lbliii.github.io/chirp/docs/routing/) |
| **Filesystem routing** | Route discovery from `pages/` with layouts | [Filesystem →](https://lbliii.github.io/chirp/docs/routing/filesystem-routing/) |
| **Templates** | Kida integration, rendering, filters | [Templates →](https://lbliii.github.io/chirp/docs/templates/) |
| **Fragments** | Render named template blocks independently | [Fragments →](https://lbliii.github.io/chirp/docs/templates/fragments/) |
| **Forms** | `form_or_errors`, form macros, validation | [Forms →](https://lbliii.github.io/chirp/docs/data/forms-validation/) |
| **Streaming** | Progressive HTML rendering via Kida | [Streaming →](https://lbliii.github.io/chirp/docs/streaming/) |
| **SSE** | Server-Sent Events for real-time updates | [SSE →](https://lbliii.github.io/chirp/docs/streaming/server-sent-events/) |
| **Middleware** | CORS, sessions, static files, security headers, custom | [Middleware →](https://lbliii.github.io/chirp/docs/middleware/) |
| **Contracts** | Validate htmx attrs, form actions, and route-bearing dialog args | [Reference →](https://lbliii.github.io/chirp/docs/reference/) |
| **Testing** | Test client, assertions, isolation utilities | [Testing →](https://lbliii.github.io/chirp/docs/testing/) |
| **Data** | Database integration and form validation | [Data →](https://lbliii.github.io/chirp/docs/data/) |
| **Optional UI layer** | `chirp-ui` companion components and styles | [chirp-ui →](https://github.com/lbliii/chirp-ui) |
📚 **Full documentation**: [lbliii.github.io/chirp](https://lbliii.github.io/chirp/)
---
## Production Deployment
Chirp apps run on **[pounce](https://github.com/lbliii/pounce)**, a production-grade ASGI server with enterprise features built-in:
### Automatic Features (Zero Configuration)
- ✅ **WebSocket compression** — 60% bandwidth reduction
- ✅ **HTTP/2 support** — Multiplexed streams, server push
- ✅ **Graceful shutdown** — Finishes active requests on SIGTERM
- ✅ **Zero-downtime reload** — `kill -SIGUSR1` for hot code updates
- ✅ **Built-in health endpoint** — `/health` for Kubernetes probes
### Production Features (Configurable)
- 📊 **Prometheus metrics** — `/metrics` endpoint for monitoring
- 🛡️ **Per-IP rate limiting** — Token bucket algorithm, configurable burst
- 📦 **Request queueing** — Load shedding during traffic spikes
- 🐛 **Sentry integration** — Automatic error tracking and reporting
- 🔄 **Multi-worker mode** — CPU-based auto-scaling
### Quick Start: Production Mode
```python
from chirp import App, AppConfig
# Production configuration
config = AppConfig(
debug=False, # ← Enables production mode
workers=4,
metrics_enabled=True,
rate_limit_enabled=True,
sentry_dsn="https://...",
)
app = App(config=config)
@app.route("/")
def index():
return "Hello, Production!"
app.run() # ← Automatically uses production server
```
### CLI Production Mode
```bash
# Development (single worker, auto-reload)
chirp run myapp:app
# Production (multi-worker, all features)
chirp run myapp:app --production --workers 4 --metrics --rate-limit
```
### Docker Deployment
```dockerfile
FROM python:3.14-slim
WORKDIR /app
COPY . .
RUN pip install bengal-chirp
CMD ["chirp", "run", "myapp:app", "--production", "--workers", "4"]
```
**Full deployment guide**: [Deployment docs](https://lbliii.github.io/chirp/docs/deployment/production/)
---
## Usage
Return Values — Type-driven content negotiation
Route functions return *values*. The framework handles content negotiation based on the type:
```python
return "Hello" # -> 200, text/html
return {"users": [...]} # -> 200, application/json
return Template("page.html", title="Home") # -> 200, rendered via Kida
return Page("search.html", "results", items=x) # -> Fragment or Template (auto)
return Fragment("page.html", "results", items=x) # -> 200, rendered block
return Stream("dashboard.html", **async_ctx) # -> 200, streamed HTML
return Suspense("dashboard.html", stats=...) # -> shell + OOB swaps
return EventStream(generator()) # -> SSE stream
return hx_redirect("/dashboard") # -> Location + HX-Redirect
return Response(body=b"...", status=201) # -> explicit control
return Redirect("/login") # -> 302
```
No `make_response()`. No `jsonify()`. The type *is* the intent.
For htmx-driven form posts or mutations that should trigger a full-page
navigation, prefer `hx_redirect()` so both plain browser and htmx requests
follow the redirect correctly.
Fragments and htmx — Render template blocks independently
Kida can render a named block from a template independently, without rendering the whole page:
```html
{# templates/search.html #}
{% extends "base.html" %}
{% block content %}
{% block results_list %}
{% for item in results %}
{{ item.title }}
{% end %}
{% endblock %}
{% endblock %}
```
```python
@app.route("/search")
async def search(request: Request):
results = await db.search(request.query.get("q", ""))
if request.is_fragment:
return Fragment("search.html", "results_list", results=results)
return Template("search.html", results=results)
```
Full page request renders everything. htmx request renders just the `results_list` block.
Same template, same data, different scope. No separate "partials" directory.
Streaming HTML — Progressive rendering
Kida renders template sections as they complete. The browser receives the shell immediately
and content fills in progressively:
```python
@app.route("/dashboard")
async def dashboard(request: Request):
return Stream("dashboard.html",
header=site_header(),
stats=await load_stats(),
activity=await load_activity(),
)
```
Server-Sent Events — Real-time HTML updates
Push Kida-rendered HTML fragments to the browser in real-time:
```python
@app.route("/notifications")
async def notifications(request: Request):
async def stream():
async for event in notification_bus.subscribe(request.user):
yield Fragment("components/notification.html", event=event)
return EventStream(stream())
```
Combined with htmx's SSE support, this enables real-time UI updates with zero client-side
JavaScript. The server renders HTML, the browser swaps it in.
Middleware — Composable request/response pipeline
No base class. No inheritance. A middleware is anything that matches the protocol:
```python
async def timing(request: Request, next: Next) -> Response:
start = time.monotonic()
response = await next(request)
elapsed = time.monotonic() - start
return response.with_header("X-Time", f"{elapsed:.3f}")
app.add_middleware(timing)
```
Built-in middleware: CORS, StaticFiles, HTMLInject, Sessions, SecurityHeaders.
Typed Contracts — Compile-time hypermedia validation
Chirp validates the server-client boundary at startup:
```python
# Prints a contract report and exits non-zero on errors.
app.check()
# Optional strict mode: treat warnings as failures too.
app.check(warnings_as_errors=True)
```
Every `hx-get`, `hx-post`, and `action` attribute in your templates is checked against the
registered route table. Every `Fragment` and `SSE` return type is checked against available
template blocks. SSE safety checks catch broken `sse-connect` / `sse-swap` structures and
unsafe inherited target scopes before runtime.
For strict CI:
```bash
chirp check myapp:app --warnings-as-errors
```
---
## Key Ideas
- **HTML over the wire.** Serve full pages, template fragments, streaming HTML, and
Server-Sent Events. Built for htmx and the modern browser.
- **Kida built in.** Same author, no seam. Fragment rendering, streaming templates, and
filter registration are first-class features, not afterthoughts.
- **Typed end-to-end.** Frozen config, frozen request, chainable response. Zero
`type: ignore` comments.
- **Free-threading native.** Designed for Python 3.14t from the first line. Immutable data
structures, ContextVar isolation.
- **Contracts, not conventions.** `app.check()` validates the full hypermedia surface at
startup.
- **UI is optional.** Build with plain templates and your own design system, or add
`chirp-ui` as a companion layer.
- **Minimal dependencies.** `kida-templates` + `anyio` + `bengal-pounce`. Everything else is optional.
---
## Documentation
📚 **[lbliii.github.io/chirp](https://lbliii.github.io/chirp/)**
| Section | Description |
|---------|-------------|
| [Get Started](https://lbliii.github.io/chirp/docs/get-started/) | Installation and quickstart |
| [Core Concepts](https://lbliii.github.io/chirp/docs/core-concepts/) | App lifecycle, return values, configuration |
| [Routing](https://lbliii.github.io/chirp/docs/routing/) | Routes, filesystem routing, requests |
| [Templates](https://lbliii.github.io/chirp/docs/templates/) | Rendering, fragments, filters |
| [Streaming](https://lbliii.github.io/chirp/docs/streaming/) | HTML streaming and Server-Sent Events |
| [Middleware](https://lbliii.github.io/chirp/docs/middleware/) | Built-in and custom middleware |
| [Data](https://lbliii.github.io/chirp/docs/data/) | Database integration and forms |
| [Testing](https://lbliii.github.io/chirp/docs/testing/) | Test client and assertions |
| [Deployment](https://lbliii.github.io/chirp/docs/deployment/) | Production deployment with Pounce |
| [Guides](https://lbliii.github.io/chirp/docs/guides/) | App shells, islands, Alpine, accessibility |
| [Tutorials](https://lbliii.github.io/chirp/docs/tutorials/) | Flask migration, htmx patterns |
| [Examples](https://lbliii.github.io/chirp/docs/examples/) | RAG demo, production stack, API |
| [Reference](https://lbliii.github.io/chirp/docs/reference/) | API documentation |
---
## Development
```bash
git clone https://github.com/lbliii/chirp.git
cd chirp
uv sync --group dev
pytest
```
---
## The Bengal Ecosystem
A structured reactive stack written in pure Python for 3.14t free-threading. Chirp is the framework; packages like `chirp-ui` sit on top as optional companions.
| | | | |
|--:|---|---|---|
| **ᓚᘏᗢ** | [Bengal](https://github.com/lbliii/bengal) | Static site generator | [Docs](https://lbliii.github.io/bengal/) |
| **∿∿** | [Purr](https://github.com/lbliii/purr) | Content runtime | — |
| **⌁⌁** | **Chirp** | Web framework ← You are here | [Docs](https://lbliii.github.io/chirp/) |
| **ʘ** | [chirp-ui](https://github.com/lbliii/chirp-ui) | Optional companion UI layer | — |
| **=^..^=** | [Pounce](https://github.com/lbliii/pounce) | ASGI server | [Docs](https://lbliii.github.io/pounce/) |
| **)彡** | [Kida](https://github.com/lbliii/kida) | Template engine | [Docs](https://lbliii.github.io/kida/) |
| **ฅᨐฅ** | [Patitas](https://github.com/lbliii/patitas) | Markdown parser | [Docs](https://lbliii.github.io/patitas/) |
| **⌾⌾⌾** | [Rosettes](https://github.com/lbliii/rosettes) | Syntax highlighter | [Docs](https://lbliii.github.io/rosettes/) |
Python-native. Free-threading ready. No npm required.
---
## License
MIT