marimo icon indicating copy to clipboard operation
marimo copied to clipboard

Multi-App Runner

Open hirolau opened this issue 11 months ago • 3 comments

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

hirolau avatar Dec 20 '24 10:12 hirolau

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

mscolnick avatar Dec 20 '24 15:12 mscolnick

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.

CGamesPlay avatar Mar 22 '25 08:03 CGamesPlay

Another drawback is that it loses all the functionality that marimo edit provides. The biggest being you cannot edit your notebooks.

cebaa avatar Oct 17 '25 18:10 cebaa