fast_app() – when speed and sensible defaults matter
Typical scenario | Why the wrapper helps |
---|---|
Proof-of-concepts, tutorials, Jupyter demos, small internal tools | One call gives you an app plus a ready-to-use route decorator: app, rt = fast_app() (fastht.ml) |
You like “batteries-included” defaults (PicoCSS, HTMX, Surreal scope JS, charset/meta tags, canonical link, session middleware, static-file routing) | Those headers and routes are injected automatically; even PicoCSS is on by default (fastht.ml) |
You want live-reload or a SQLite/Surreal “FastLite” DB with minimal ceremony | The wrapper selects FastHTMLWithLiveReload when live=True , and can create tables + dataclasses when db_file /tbls are supplied (GitHub) |
FastHTML() – when you need full control
Typical scenario | Why you’d skip the wrapper |
---|---|
Larger code-bases, libraries, or mixed ASGI projects | FastHTML is a thin subclass of Starlette; you can mount it, compose routers, or subclass it just as you would any ASGI app (fastht.ml) |
Non-default headers, your own CSS/JS stack, custom session or CORS middleware, or no database at all | You pass only the arguments you need; nothing is silently added. |
Fine-grained lifecycle & testing | Direct instantiation exposes every Starlette hook (routes , middleware , lifespan , etc.) and is what the test client examples use (fastht.ml) |
- Start with
fast_app()
– it covers 80 % of cases and lets you ship a working app in a handful of lines. - Switch to
FastHTML()
only when those smart defaults get in your way—e.g. you need a different CSS framework, must disable HTMX, manage sessions differently, or embed the app inside a larger ASGI ecosystem.
Technically, fast_app()
just builds the same FastHTML
object and then returns it, so there is no performance penalty—only extra convenience.