# fasthtml Module Documentation
## fasthtml.authmw
- `class BasicAuthMiddleware`
- `def __init__(self, app, cb, skip)`
- `def __call__(self, scope, receive, send)`
- `def authenticate(self, conn)`
## fasthtml.cli
- `@call_parse def railway_link()`
Link the current directory to the current project's Railway service
- `@call_parse def railway_deploy(name, mount)`
Deploy a FastHTML app to Railway
## fasthtml.components
> `ft_html` and `ft_hx` functions to add some conveniences to `ft`, along with a full set of basic HTML components, and functions to work with forms and `FT` conversion
- `def show(ft, *rest)`
Renders FT Components into HTML within a Jupyter notebook.
- `def File(fname)`
Use the unescaped text in file `fname` directly
- `def fill_form(form, obj)`
Fills named items in `form` using attributes in `obj`
- `def fill_dataclass(src, dest)`
Modifies dataclass in-place and returns it
- `def find_inputs(e, tags, **kw)`
Recursively find all elements in `e` with `tags` and attrs matching `kw`
- `def html2ft(html, attr1st)`
Convert HTML to an `ft` expression
- `def sse_message(elm, event)`
Convert element `elm` into a format suitable for SSE streaming
## fasthtml.core
> The `FastHTML` subclass of `Starlette`, along with the `RouterX` and `RouteX` classes it automatically uses.
- `def parsed_date(s)`
Convert `s` to a datetime
- `def snake2hyphens(s)`
Convert `s` from snake case to hyphenated and capitalised
- `@dataclass class HtmxHeaders`
- `def __bool__(self)`
- `def __init__(self, boosted, current_url, history_restore_request, prompt, request, target, trigger_name, trigger)`
- `def str2int(s)`
Convert `s` to an `int`
- `def str2date(s)`
`date.fromisoformat` with empty string handling
- `@dataclass class HttpHeader`
- `def __init__(self, k, v)`
- `@use_kwargs_dict(**htmx_resps) def HtmxResponseHeaders(**kwargs)`
HTMX response headers
- `def form2dict(form)`
Convert starlette form data to a dict
- `def parse_form(req)`
Starlette errors on empty multipart forms, so this checks for that situation
- `def flat_xt(lst)`
Flatten lists
- `class Beforeware`
- `def __init__(self, f, skip)`
- `def EventStream(s)`
Create a text/event-stream response from `s`
- `class WS_RouteX`
- `def __init__(self, app, path, recv, conn, disconn)`
- `def flat_tuple(o)`
Flatten lists
- `class Redirect`
Use HTMX or Starlette RedirectResponse as required to redirect to `loc`
- `def __init__(self, loc)`
- `def __response__(self, req)`
- `class RouteX`
- `def __init__(self, app, path, endpoint)`
- `class RouterX`
- `def __init__(self, app, routes, redirect_slashes, default)`
- `def add_route(self, path, endpoint, methods, name, include_in_schema)`
- `def add_ws(self, path, recv, conn, disconn, name)`
- `def def_hdrs(htmx, ct_hdr, ws_hdr, surreal)`
Default headers for a FastHTML app
- `class FastHTML`
- `def __init__(self, debug, routes, middleware, exception_handlers, on_startup, on_shutdown, lifespan, hdrs, ftrs, before, after, ws_hdr, ct_hdr, surreal, htmx, default_hdrs, sess_cls, secret_key, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, key_fname, htmlkw, **bodykw)`
- `def ws(self, path, conn, disconn, name)`
Add a websocket route at `path`
- `@patch def route(self, path, methods, name, include_in_schema)`
Add a route at `path`
- `def serve(appname, app, host, port, reload, reload_includes, reload_excludes)`
Run the app in an async server, with live reload set as the default.
- `class Client`
A simple httpx ASGI client that doesn't require `async`
- `def __init__(self, app, url)`
- `def cookie(key, value, max_age, expires, path, domain, secure, httponly, samesite)`
Create a 'set-cookie' `HttpHeader`
- `@patch def static_route_exts(self, prefix, static_path, exts)`
Add a static route at URL path `prefix` with files from `static_path` and `exts` defined by `reg_re_param()`
- `@patch def static_route(self, ext, prefix, static_path)`
Add a static route at URL path `prefix` with files from `static_path` and single `ext` (including the '.')
- `class MiddlewareBase`
- `def __call__(self, scope, receive, send)`
- `class FtResponse`
Wrap an FT response with any Starlette `Response`
- `def __init__(self, content, status_code, headers, cls, media_type, background)`
- `def __response__(self, req)`
## fasthtml.fastapp
> The `fast_app` convenience wrapper
- `def fast_app(db_file, render, hdrs, ftrs, tbls, before, middleware, live, debug, routes, exception_handlers, on_startup, on_shutdown, lifespan, default_hdrs, pico, surreal, htmx, ws_hdr, secret_key, key_fname, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, htmlkw, bodykw, reload_attempts, reload_interval, static_path, **kwargs)`
Create a FastHTML or FastHTMLWithLiveReload app.
## fasthtml.js
> Basic external Javascript lib wrappers
- `def light_media(css)`
Render light media for day mode views
- `def dark_media(css)`
Render dark media for nught mode views
- `def MarkdownJS(sel)`
Implements browser-based markdown rendering.
- `def HighlightJS(sel, langs, light, dark)`
Implements browser-based syntax highlighting. Usage example [here](/tutorials/quickstart_for_web_devs.html#code-highlighting).
## fasthtml.jupyter
- `def nb_serve(app, log_level, port, **kwargs)`
Start a Jupyter compatible uvicorn server with ASGI `app` on `port` with `log_level`
- `def nb_serve_async(app, log_level, port, **kwargs)`
Async version of `nb_serve`
- `def is_port_free(port, host)`
Check if `port` is free on `host`
- `def wait_port_free(port, host, max_wait)`
Wait for `port` to be free on `host`
- `class JupyUvi`
Start and stop a Jupyter compatible uvicorn server with ASGI `app` on `port` with `log_level`
- `def __init__(self, app, log_level, port, start, **kwargs)`
- `def start(self)`
- `def stop(self)`
- `def FastJupy(hdrs, middleware, **kwargs)`
Same as FastHTML, but with Jupyter compatible middleware and headers added
- `def HTMX(host, port, iframe_height)`
An iframe which displays the HTMX application in a notebook.
- `def jupy_app(pico, hdrs, middleware, **kwargs)`
Same as `fast_app` but for Jupyter notebooks
## fasthtml.live_reload
- `class FastHTMLWithLiveReload`
`FastHTMLWithLiveReload` enables live reloading.
This means that any code changes saved on the server will automatically
trigger a reload of both the server and browser window.
How does it work?
- a websocket is created at `/live-reload`
- a small js snippet `LIVE_RELOAD_SCRIPT` is injected into each webpage
- this snippet connects to the websocket at `/live-reload` and listens for an `onclose` event
- when the `onclose` event is detected the browser is reloaded
Why do we listen for an `onclose` event?
When code changes are saved the server automatically reloads if the --reload flag is set.
The server reload kills the websocket connection. The `onclose` event serves as a proxy
for "developer has saved some changes".
Usage
>>> from fasthtml.common import *
>>> app = FastHTMLWithLiveReload()
Run:
run_uv()
- `def __init__(self, *args, **kwargs)`
## fasthtml.oauth
> Basic scaffolding for handling OAuth
- `class GoogleAppClient`
A `WebApplicationClient` for Google oauth2
- `def __init__(self, client_id, client_secret, code, scope, **kwargs)`
- `@classmethod def from_file(cls, fname, code, scope, **kwargs)`
- `class GitHubAppClient`
A `WebApplicationClient` for GitHub oauth2
- `def __init__(self, client_id, client_secret, code, scope, **kwargs)`
- `class HuggingFaceClient`
A `WebApplicationClient` for HuggingFace oauth2
- `def __init__(self, client_id, client_secret, code, scope, state, **kwargs)`
- `class DiscordAppClient`
A `WebApplicationClient` for Discord oauth2
- `def __init__(self, client_id, client_secret, is_user, perms, scope, **kwargs)`
- `def login_link(self)`
- `def parse_response(self, code)`
- `@patch def login_link(self, redirect_uri, scope, state)`
Get a login link for this client
- `def redir_url(request, redir_path)`
Get the redir url for the host in `request`
- `@patch def parse_response(self, code, redirect_uri)`
Get the token from the oauth2 server response
- `@patch def get_info(self, token)`
Get the info for authenticated user
- `@patch def retr_info(self, code, redirect_uri)`
Combines `parse_response` and `get_info`
- `@patch def retr_id(self, code, redirect_uri)`
Call `retr_info` and then return id/subscriber value
- `class OAuth`
- `def __init__(self, app, cli, skip, redir_path, logout_path, login_path)`
- `def redir_url(self, req)`
- `def login_link(self, req, scope, state)`
- `def login(self, info, state)`
- `def logout(self, session)`
- `def chk_auth(self, info, ident, session)`
## fasthtml.pico
> Basic components for generating Pico CSS tags
- `@delegates(ft_hx, keep=True) def Card(*c, **kwargs)`
A PicoCSS Card, implemented as an Article with optional Header and Footer
- `@delegates(ft_hx, keep=True) def Group(*c, **kwargs)`
A PicoCSS Group, implemented as a Fieldset with role 'group'
- `@delegates(ft_hx, keep=True) def Search(*c, **kwargs)`
A PicoCSS Search, implemented as a Form with role 'search'
- `@delegates(ft_hx, keep=True) def Grid(*c, **kwargs)`
A PicoCSS Grid, implemented as child Divs in a Div with class 'grid'
- `@delegates(ft_hx, keep=True) def DialogX(*c, **kwargs)`
A PicoCSS Dialog, with children inside a Card
- `@delegates(ft_hx, keep=True) def Container(*args, **kwargs)`
A PicoCSS Container, implemented as a Main with class 'container'
## fasthtml.svg
> Simple SVG FT elements
- `def Svg(*args, **kwargs)`
An SVG tag; xmlns is added automatically, and viewBox defaults to height and width if not provided
- `@delegates(ft_hx) def ft_svg(tag, *c, **kwargs)`
Create a standard `FT` element with some SVG-specific attrs
- `@delegates(ft_svg) def Rect(width, height, x, y, fill, stroke, stroke_width, rx, ry, **kwargs)`
A standard SVG `rect` element
- `@delegates(ft_svg) def Circle(r, cx, cy, fill, stroke, stroke_width, **kwargs)`
A standard SVG `circle` element
- `@delegates(ft_svg) def Ellipse(rx, ry, cx, cy, fill, stroke, stroke_width, **kwargs)`
A standard SVG `ellipse` element
- `def transformd(translate, scale, rotate, skewX, skewY, matrix)`
Create an SVG `transform` kwarg dict
- `@delegates(ft_svg) def Line(x1, y1, x2, y2, stroke, w, stroke_width, **kwargs)`
A standard SVG `line` element
- `@delegates(ft_svg) def Polyline(*args, **kwargs)`
A standard SVG `polyline` element
- `@delegates(ft_svg) def Polygon(*args, **kwargs)`
A standard SVG `polygon` element
- `@delegates(ft_svg) def Text(*args, **kwargs)`
A standard SVG `text` element
- `class PathFT`
- `def M(self, x, y)`
Move to.
- `def L(self, x, y)`
Line to.
- `def H(self, x)`
Horizontal line to.
- `def V(self, y)`
Vertical line to.
- `def Z(self)`
Close path.
- `def C(self, x1, y1, x2, y2, x, y)`
Cubic Bézier curve.
- `def S(self, x2, y2, x, y)`
Smooth cubic Bézier curve.
- `def Q(self, x1, y1, x, y)`
Quadratic Bézier curve.
- `def T(self, x, y)`
Smooth quadratic Bézier curve.
- `def A(self, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x, y)`
Elliptical Arc.
- `def SvgOob(*args, **kwargs)`
Wraps an SVG shape as required for an HTMX OOB swap
- `def SvgInb(*args, **kwargs)`
Wraps an SVG shape as required for an HTMX inband swap
## fasthtml.xtend
> Simple extensions to standard HTML components, such as adding sensible defaults
- `@delegates(ft_hx, keep=True) def A(*c, **kwargs)`
An A tag; `href` defaults to '#' for more concise use with HTMX
- `@delegates(ft_hx, keep=True) def AX(txt, hx_get, target_id, hx_swap, href, **kwargs)`
An A tag with just one text child, allowing hx_get, target_id, and hx_swap to be positional params
- `@delegates(ft_hx, keep=True) def Form(*c, **kwargs)`
A Form tag; identical to plain `ft_hx` version except default `enctype='multipart/form-data'`
- `@delegates(ft_hx, keep=True) def Hidden(value, id, **kwargs)`
An Input of type 'hidden'
- `@delegates(ft_hx, keep=True) def CheckboxX(checked, label, value, id, name, **kwargs)`
A Checkbox optionally inside a Label, preceded by a `Hidden` with matching name
- `@delegates(ft_html, keep=True) def Script(code, **kwargs)`
A Script tag that doesn't escape its code
- `@delegates(ft_html, keep=True) def Style(*c, **kwargs)`
A Style tag that doesn't escape its code
- `def double_braces(s)`
Convert single braces to double braces if next to special chars or newline
- `def undouble_braces(s)`
Convert double braces to single braces if next to special chars or newline
- `def loose_format(s, **kw)`
String format `s` using `kw`, without being strict about braces outside of template params
- `def ScriptX(fname, src, nomodule, type, _async, defer, charset, crossorigin, integrity, **kw)`
A `script` element with contents read from `fname`
- `def replace_css_vars(css, pre, **kwargs)`
Replace `var(--)` CSS variables with `kwargs` if name prefix matches `pre`
- `def StyleX(fname, **kw)`
A `style` element with contents read from `fname` and variables replaced from `kw`
- `def Nbsp()`
A non-breaking space
- `def Surreal(code)`
Wrap `code` in `domReadyExecute` and set `m=me()` and `p=me('-')`
- `def On(code, event, sel, me)`
An async surreal.js script block event handler for `event` on selector `sel,p`, making available parent `p`, event `ev`, and target `e`
- `def Prev(code, event)`
An async surreal.js script block event handler for `event` on previous sibling, with same vars as `On`
- `def Now(code, sel)`
An async surreal.js script block on selector `me(sel)`
- `def AnyNow(sel, code)`
An async surreal.js script block on selector `any(sel)`
- `def run_js(js, id, **kw)`
Run `js` script, auto-generating `id` based on name of caller if needed, and js-escaping any `kw` params
- `def jsd(org, repo, root, path, prov, typ, ver, esm, **kwargs)`
jsdelivr `Script` or CSS `Link` tag, or URL
- `@delegates(ft_hx, keep=True) def Titled(title, *args, **kwargs)`
An HTML partial containing a `Title`, and `H1`, and any provided children
- `def Socials(title, site_name, description, image, url, w, h, twitter_site, creator, card)`
OG and Twitter social card headers
- `def Favicon(light_icon, dark_icon)`
Light and dark favicon headers