FastHTML
FastHTML is a lightweight and performant Python library designed for building dynamic HTML web applications with minimal code. It leverages ASGI for high performance and integrates well with technologies like HTMX for interactive user experiences. As of version 0.13.3, it is under active development with frequent minor releases.
Warnings
- gotcha FastHTML implicitly renders HTML components returned from route functions. If you need to return a custom Starlette/FastAPI `Response` object (e.g., `RedirectResponse`, `JSONResponse`), ensure it's explicitly imported and returned, as FastHTML's auto-rendering will be bypassed.
- gotcha Handling complex form data, especially file uploads or multipart forms, might require using the `Capture` component. While simple form parameters are automatically injected into route function arguments, accessing raw request bodies or specific file metadata is less direct.
- breaking FastHTML is actively developed and currently below version 1.0. Minor version updates may introduce breaking changes to the API, internal structures, or default behaviors without a major version increment. Always review release notes carefully when upgrading.
- gotcha Integrating custom Starlette middleware or lifespan events (`on_startup`, `on_shutdown`) requires understanding FastHTML's wrappers. Direct use of `app.add_middleware` might be less idiomatic than expected, and lifespan events are managed via a dedicated `Lifespan` class.
Install
-
pip install fasthtml uvicorn
Imports
- FastHTML
from fasthtml import FastHTML
- HTML
from fasthtml.common import HTML
- H1
from fasthtml.common import H1
- P
from fasthtml.common import P
- A
from fasthtml.common import A
- Capture
from fasthtml.components import Capture
Quickstart
from fasthtml.common import *
from uvicorn import run
app = FastHTML()
# Global counter for demonstration
counter_val = 0
@app.get('/')
def home():
return (
Title('FastHTML Counter with HTMX'),
H1('Click Counter'),
P(
'Count: ',
A(
counter_val,
id='count',
_hx_get='/count',
_hx_swap='outerHTML',
_hx_trigger='click'
)
)
)
@app.get('/count')
def count_update():
global counter_val
counter_val += 1
return A(
counter_val,
id='count',
_hx_get='/count',
_hx_swap='outerHTML',
_hx_trigger='click'
)
if __name__ == '__main__':
# Run with uvicorn: uvicorn main:app --reload
run(app, port=8000)