The Landscape
Flask (2010), Django (2005), and FastAPI (2018) were designed for a different web. Each makes assumptions that don't match where the web platform is in 2026.
Feature Comparison
| Feature | Chirp | Flask | FastAPI | Django |
|---|---|---|---|---|
| Fragment rendering | Built-in | No | No | No |
| Streaming HTML | Built-in | No | Manual | No |
| Server-Sent Events | Built-in | Extension | Manual | Channels |
| htmx integration | First-class | Extension | Manual | Extension |
| Typed contracts | app.check() |
No | OpenAPI | No |
| Template engine | Kida (built-in) | Jinja2 (plugin) | None | DTL (built-in) |
| Free-threading | Native | No | No | No |
| ASGI | Native | Via adapter | Native | Via ASGI handler |
| Type safety | Strict (ty clean) | Partial | Strong | Partial |
vs Flask
Flask got the surface right. Chirp starts from the same place -- decorators, return values, simple setup.
# Flask
@app.route("/")
def index():
return render_template("index.html", title="Home")
# Chirp
@app.route("/")
def index():
return Template("index.html", title="Home")
Where Chirp diverges:
- Fragments: Flask can't render a named block from a template. You need separate partial templates and manual htmx wiring. Chirp renders any block independently.
- Streaming: Flask's
Response(generate())is manual chunked encoding. Chirp'sStreamintegrates with kida's streaming renderer. - Immutability: Flask's
requestis a thread-local proxy. Chirp'sRequestis a frozen dataclass. - Configuration: Flask uses a dict (
app.config["SECRET_KEY"]). Chirp uses a frozen dataclass with IDE autocomplete.
When to use Flask: Existing Flask apps, extensive ecosystem of extensions, WSGI deployment.
vs FastAPI
FastAPI assumes you serve JSON to a JavaScript frontend. It has no template story.
# FastAPI
@app.get("/users/{id}")
async def get_user(id: int):
return {"id": id, "name": "Alice"}
# Chirp
@app.route("/users/{id:int}")
def get_user(id: int):
return Template("user.html", user=get_user(id))
Where Chirp diverges:
- HTML-first: Chirp is designed to serve HTML. FastAPI is designed to serve JSON.
- Templates: Chirp has kida built in with fragment rendering. FastAPI has
Jinja2Templatesas an afterthought. - Validation: FastAPI uses Pydantic for request validation. Chirp uses form validation rules and typed path parameters.
- OpenAPI: FastAPI auto-generates OpenAPI specs. Chirp validates hypermedia contracts instead.
When to use FastAPI: JSON APIs, Pydantic-heavy data validation, OpenAPI documentation.
vs Django
Django is a batteries-included framework. Chirp is not.
Where Chirp diverges:
- Scope: Django includes ORM, admin, auth, forms, migrations, email, caching. Chirp includes routing, templates, middleware, and SSE.
- Templates: Django Template Language cannot render individual blocks. Chirp + kida can.
- Real-time: Django requires Channels for WebSocket/SSE. Chirp has SSE built in.
- Size: Django is ~300k lines. Chirp is ~5k lines (53 modules).
When to use Django: Full-featured applications, tight deadlines, admin interfaces, established teams.
When to Use Chirp
Chirp is designed for:
- htmx-driven applications where the server renders HTML fragments
- Real-time dashboards with streaming HTML and SSE
- Modern web apps that leverage the browser's native capabilities
- Python 3.14t applications that want true free-threading
- Developers who want to own their stack -- compose exactly what you need
Chirp is not designed for:
- JSON APIs (use FastAPI)
- Full-featured apps with admin panels (use Django)
- Apps that need WSGI compatibility (use Flask)
- Teams that need maximum ecosystem support (use Flask or Django)
Next Steps
- Philosophy -- Why Chirp makes these choices
- Quickstart -- Try it yourself
- Coming from Flask -- Migration guide