Try an interactive version of this dialog: Sign up at solve.it.com, click Upload, and pass this URL.

1. FastHTML Setup

from fastcore.utils import *
from fasthtml.common import *
from fasthtml.jupyter import *
import fasthtml.components as fc
import httpx

Idempotent server startup for CRAFT files

On each kernel start/restart:

  1. If nothing is on port 8000 → xargs -r does nothing (the -r flag means "don't run if no input")
  2. If something is on port 8000 → it gets killed, then your server takes over

This ensures the FastHTML server always starts cleanly, regardless of prior state.

import subprocess

def kill_port(port=8000):
    subprocess.run(f"lsof -ti:{port} | xargs -r kill -9", shell=True)

kill_port()
hdrs = (
    Script(src='https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4'),
    Link(href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css', integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=", crossorigin="", rel='stylesheet', type='text/css'),
    Script(src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js", integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=", crossorigin=""),
)
# Note: We need to set a custom session cookie for FastHTML sessions to work in SolveIt since (for now) SolveIt uses the default one (this might change in the future)
if 'srv' not in globals() or not srv:
    app = FastHTML(hdrs=hdrs, session_cookie='fh_template_session')
    rt = app.route
    srv = JupyUvi(app)
# used to run our app later

def get_preview(app): return partial(HTMX, app=app, host=None, port=None)
preview = get_preview(app)

2. Add Leaflet Route

@rt enables route creation directly in SolveIt dialogs!

@rt
def index():
    return Div(
            Div(id="map", style="width:100vw;height:100vh;"),
            Script("""
              var map = L.map('map').setView([51.505, -0.09], 13);
              L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: '© OpenStreetMap'
              }).addTo(map);
            """)
    )

5. Run FastHTML App

import json
from IPython.display import IFrame
IFrame(f"https://{json.loads(os.environ['PUBLIC_DOMAINS'])['8000']}", width=800, height=500)