core
Server startup: bring the boopiter web app up on a port (or cleanly relaunch it), refusing to stomp on a port held by something that isn’t boopiter. Precompiles Tailwind once, then starts the server;
launch is the entry point the CLI and notebook both call.
Port management
Before starting, boopiter checks who owns the target port: _port_owner pings it to tell a running boopiter from someone else from nobody, and _kill_port frees a port held by a previous boopiter run – so relaunching is safe but an unrelated service is never killed.
Tailwind precompile
_build_tailwind compiles a static Tailwind CSS file once at launch, replacing the CDN’s in-browser JIT compiler – faster page loads and no runtime CDN dependency.
Launching
launch ties it together – free the port if it’s ours, build the CSS, start the server. It’s the @call_parse entry point exposed on the command line.
launch
def launch(
nbfile:Annotated=None, # .ipynb file to load on startup
port:int=8000, # the port to serve boopiter on
no_auth:bool=False, # skip token-gating the server -- ONLY on a network you fully trust; every code cell already runs with this process's own permissions, so an unauthed boopiter is equivalent to handing out a shell
):Launch (or relaunch) the boopiter server; refuses to touch a port held by something that isn’t boopiter