Every framework starts with a "why." For Flaxon, the answer is rooted in a simple observation: Python developers shouldn't have to choose between simplicity and power.
After years of building web applications with Flask, Django, FastAPI, and Node.js, I noticed a recurring pattern. Developers would start with a simple framework, only to find themselves fighting against its limitations as their application grew. Or they would choose a batteries-included framework, only to feel constrained by its opinions on how things should be done.
Flaxon is my attempt to solve this problem. Here's the philosophy that guides its development.
Python web development faces three practical choices:
None of these options are wrong. But they all involve a trade-off that I believe developers shouldn't have to make.
Flaxon explores a fourth option: retain Python while combining a small entry experience with optional production structure and async-first networking.
This is guided by five core principles.
Small applications should start in one file without generators or mandatory architecture. Flaxon provides a minimal entry point that lets you get started quickly.
from flaxon import Flaxon
app = Flaxon("my-app")
@app.get("/")
async def home():
return {"message": "Hello"}
No configuration files. No folder structure. No mandatory ORM or database setup. Just code.
As your application grows, Flaxon provides optional structure without requiring a complete rewrite. You can introduce routers, services, middleware, and plugins incrementally.
from flaxon import Router
api = Router(prefix="/api/v1")
@api.get("/users")
async def list_users():
return [{"id": 1, "name": "Alice"}]
app.include_router(api)
The structure grows with your application, not before it.
Flaxon treats JSON APIs as a first-class default. HTML rendering through Jinax is optional and lazily loaded. If you're building an API, you don't pay the cost of template rendering.
# API-only - no template dependencies
@app.get("/api/users")
async def get_users():
return [{"id": 1, "name": "Alice"}]
# With templates (optional)
from flaxon.jinax import Jinax
app.use_templates(Jinax("templates"))
Flaxon does not care about your frontend, database, ORM, or client technology. Use React, Vue, Angular, Kotlin, Java, Flutter, or plain API clients. Use PostgreSQL, MongoDB, Redis, or custom storage.
The framework owns transport and developer ergonomics. It does not own the product's user-interface language.
Framework APIs should be explicit enough to debug and profile without hidden magic. Flaxon's debugger explains failures in plain language with request context.
# Clear, explicit error messages
from flaxon import HTTPException
@app.get("/users/<int:user_id>")
async def get_user(user_id: int):
if user_id == 0:
raise HTTPException(400, "Invalid user ID", code="FX-INVALID-ID")
if user_id == 404:
raise HTTPException(404, "User not found", code="FX-USER-404")
return {"id": user_id, "name": f"User {user_id}"}
ASGI (Asynchronous Server Gateway Interface) is the modern standard for Python web servers. It supports HTTP, WebSocket, and lifespan events in a single interface, making it ideal for async-first applications.
By building on ASGI, Flaxon gains:
Flaxon represents a belief that Python developers deserve a framework that grows with them. A framework that doesn't force them to choose between simplicity and power, between structure and freedom, between ease of use and high performance.
It's a framework for the modern web — where backends serve many clients, where real-time communication is expected, and where developers should be able to focus on building great applications, not fighting their tools.
That's Flaxon. And we're just getting started.
— Aldane Hutchinson, Creator & Maintainer