Useful patterns for Python notebook library, Marimo.
marimo is a Python interactive notebook framework, similar to Jupyter Notebook and Streamlit.
Marimo compiles each cell into a Python function and represents all cells as nodes in a directed acyclic graph (DAG). When a cell changes, its dependent downstream cells are re-executed automatically, so you never have to hunt for and rerun stale cells as in Jupyter Notebooks. This reactive execution model, similar to modern JavaScript UI frameworks, enables more intuitive and efficient interfaces. If you are deploying your notebook as a prototype app, Marimo certainly beats Streamlit’s linear, full-script rerun approach.
Also check the official user guide and reference.
Bootstrapping
Although Marimo files are simply Python scripts, Marimo runtime only recognizes files in a certain format. However, the CLI hasn't provide a command to init a notebook without starting the runtime. So you can use the following snippet to bootstrap.
# /// script
# [tool.marimo]
# ///
import marimo
__generated_with = "0.18.1"
app = marimo.App(width="medium")
@app.cell
def _():
import marimo as mo
return (mo,)
if __name__ == "__main__":
app.run() VS Code Snippet
{
"Init Marimo": {
"prefix": "$marimo_init",
"body": [
"# /// script",
"# [tool.marimo]",
"# ///",
"",
"import marimo",
"__generated_with = \"0.18.1\"",
"app = marimo.App(width=\"medium\")",
"",
"@app.cell",
"def _():",
" import marimo as mo",
" return (mo,)",
"",
"",
"if __name__ == \"__main__\":",
" app.run()",
"",
],
"description": "Initialize a Marimo app with a default cell importing marimo as mo"
}
}Arbitrary JavaScript
Often running arbitrary JavaScript on the client side is necessary. For example, recording keyboard events. Iframes don’t always work well. The solution is to create an anywidget and embed JavaScript in there.
This code doesn’t sanitize its JavaScript script, so you should never pass user written content to it 🙈.
Implementation
import textwrap
import marimo as mo
import anywidget
def Arbitrary(script: str, *, visualize_err: bool = False) -> mo.ui.anywidget:
"""A Marimo component that runs arbitrary JavaScript in the notebook front-end.
Args:
script (str): The JavaScript code to run.
visualize_err (bool, optional): Whether to visualize errors in the front-end. Defaults to False.
Returns:
mo.ui.anywidget: The Marimo anywidget component.
"""
script_visualize_err = textwrap.dedent(f"""
const pre = document.createElement("pre");
pre.textContent = "An error occured in JavaScript:\\n" + String(error);
// Simulates Marimo error message
pre.className = "text-sm p-2 border whitespace-pre-wrap overflow-hidden text-error border---red-6 shadow-error bg---red-1 hover:bg---red-3";
el.replaceChildren(pre);
""") if visualize_err else ""
script = textwrap.dedent(f"""
function render({{ el, model }}) {{
try {{
{script}
}} catch (error) {{
console.error("[ArbitraryWidget]", error);
{script_visualize_err}
}}
}}
export default {{ render }};
""")
ArbitraryWidget = type("ArbitraryWidget", (anywidget.AnyWidget,), {
"_esm": script,
})
return mo.ui.anywidget(ArbitraryWidget())Then you can use it to wrap arbitrary JavaScript execution.
Arbitrary(r"""
alert("Hello from the frontend!");
""")