FastHTML patching

Patches and utilities for FastHTML notebook integration

FastHTML Bridge display

  1. This functionality patches FastHTML’s IPython display system
  2. This implementation:
    • Overrides all FT IPython MIME methods
    • Uses bridge_cfg.auto_show for display opt-in

This is a convenience and not core of this proof-of-concept notebooks.

fh_cfg['auto_id'] = False
bridge_cfg.auto_show = False
d = Div(style='color: red;', hx_trigger='click')(Text('Hi!'))
print(f"d: \n{d}"); display(Markdown('----'))
print(f"showtags(d): \n{showtags(d)}"); display(Markdown('----'))
display(Markdown(highlight(d)+'\n----'))
show(d)
d: 
<div hx-trigger="click" style="color: red;"><text>Hi!</text></div>

showtags(d): 
<code><pre>
&lt;div hx-trigger=&quot;click&quot; style=&quot;color: red;&quot;&gt;
&lt;text&gt;Hi!&lt;/text&gt;&lt;/div&gt;

</code></pre>

<div hx-trigger="click" style="color: red;">
<text>Hi!</text></div>

Hi!
Div("I'm a Div!")
<div>I&#x27;m a Div!</div>
@FC.patch
def _repr_mimebundle_(self: FT, include=None, exclude=None):
    mb = {'text/plain': repr(self)}
    if bridge_cfg.auto_show: mb['text/html'] = self.__html__()
    else: mb['text/markdown'] = self._repr_markdown_()
    return mb
Div('me too!')
<div>me too!</div>
with bridge_cfg(auto_show=True):
    display(Div("But I'm prettier!"))
But I'm prettier!
Div('back to tags!')
<div>back to tags!</div>
bridge_cfg.auto_show = True
ft.Details(open=True)(ft.Summary('dddd'), ft.Pre('eeee'))
dddd
eeee
with bridge_cfg(auto_show=False): display(ft.Button('ffff'))
ft.Button('ffff')
<button>ffff</button>

Revert to FT usual.

del FT._repr_mimebundle_  # type: ignore
Div("I'm a Div!")
<div>I&#x27;m a Div!</div>

FastHTML Jupyter display

Opt-in to display FastHTML objects in the notebook as HTML instead of the default markdown repr.

Warning

Note recent FastHTML v0.9.0 has improved Jupyter support substancially and now have this same functionality (with render_ft, in v0.9.1 on by default).

Unfortunately, current implementation doesn’t work in VSCode/Cursor and probably any other Jupyter-ish environment that sandbox notebook outputs.

In VSCode/Cursor besides that, render_ft doesn’t work as expected, as Quarto renders markdown in a static shadow-root.

Patching FastHTML jupyter to work in VSCode


source

JupyUviB

 JupyUviB (app, log_level='error', host='0.0.0.0', port=8000, start=True,
           **kwargs)

Start and stop a Jupyter compatible uvicorn server with ASGI app on port with log_level

# type: ignore

app = FastHTML()
rt = app.route

@app.route
def index(): return 'hi'

port = 8000
server = JupyUviB(app, port=port)
get(f'http://localhost:{port}').text
'hi'
fh_cfg['auto_id']=True
show(Script(src='https://unpkg.com/htmx.org@2.0.4/dist/htmx.js'), fhjsscr, scopesrc, surrsrc)
clear_output()  # so it doesn't import on notebook load
display(Javascript('''
if (window.htmx) htmx.process(document.body);
'''))
clear_output()
render_ft()

After importing fasthtml.jupyter and calling render_ft(), FT components render directly in the notebook.

(c := Div('Cogito ergo sum'))
Cogito ergo sum

Handlers are written just like a regular web app:

# type: ignore

@rt
def hoho(): return P('loaded!'), Div('hee hee', id=c, hx_swap_oob='true')

All the usual hx_* attributes can be used:

P('not loaded', hx_get=hoho, hx_trigger='load')  # type: ignore

not loaded

FT components can be used directly both as id values and as hx_target values.

(c := Div(''))
# type: ignore

@rt
def foo(): return Div('foo bar')

P('hi', hx_get=foo, hx_trigger='load', hx_target=c)

hi

Stop server

server.stop()