marimo
marimo copied to clipboard
Multi-App Runner
Description
I see great use of Marimo at my organization. We have a lot of small code snippets that people want "appified". I have demonstrated a few apps in run mode and gotten great feedback.
The only problem I would see in utilizing it would be that if I have 20 apps I want my users to explore, they need to know the command and switching between apps in run mode would be quite annoying
I would like to give the user 1 command, and some way of exploring and launching apps.
Suggested solution
I suggest some multi-app runner that show the users a list of apps, and will let them click on it to start that app. Perhaps the multi-app runner would use metadata from the notebooks to show a description for each, explaining what the app does to the user.
For example: Run 2 apps:
marimo run order_tracker.py order_statistics.py
Or run all apps in a folder:
marimo run --folder /path/to/folder/containing/multiple/marimo/notebooks
Would launch a web page showing the user a list of applications in run mode:
Marimo Apps Browser
App1: Order Tracker App
- Track an specific order by entering the ID. Will show current status and calculate expected delivery time as well as open issues. (This metadata would be app-specific and stored in the notebook somehow)
App 2: Order Statistics
- Show statistics and KPIs for recent Order Creation
Alternative
No response
Additional context
No response
This makes sense. we can likely re-use the current homepage from marimo edit. We would just need to make sure we restrict usage to just those files.
In the meantime, you could write your own python file which also allows you to customize the gallery of notebooks.
from typing import Annotated, Callable, Coroutine
from fastapi.responses import HTMLResponse, RedirectResponse
import marimo
from fastapi import FastAPI, Form, Request, Response
from pathlib import Path
server = marimo.create_asgi_app()
app_names: list[str] = []
# Get args from command line
parser = argparse.ArgumentParser()
parser.add_argument("--folder", type=str)
args = parser.parse_args()
notebooks_dir = Path(args.folder)
for filename in sorted(notebooks_dir.iterdir()):
if filename.suffix == ".py":
app_name = filename.stem
server = server.with_app(path=f"/{app_name}", root=filename)
app_names.append(app_name)
# Create a FastAPI app
app = FastAPI()
app.mount("/", server.build())
# Add an index page
@app.get("/", response_class=HTMLResponse)
async def index():
links = "\n".join(
f'<p><a href="/{name}">{name.replace("_", " ").title()}</a></p>'
for name in app_names
)
return f"""
<html>
<head><title>marimo</title></head>
<body>
<h1>marimo notebooks</h1>
{links}
</body>
</html>
"""
# Run the server
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
python gallery.py --folder /path/to/notebooks
You could also host this Python file somewhere and do uv run https://<org>.com/assets/gallery.py --folder /path/to/notebooks
The biggest drawback I see with this approach (marimo.create_asgi_app) is that you cannot use sandboxing with it. Note that this is also a limitation when using marimo edit. So, caveat emptor, this method works but you should opt for using a pyproject.toml to keep all dependencies in sync for the entire notebook gallery.
Also, you'll need to move the app.mount call to below the def index or else the index route will never be matched.
Another drawback is that it loses all the functionality that marimo edit provides. The biggest being you cannot edit your notebooks.