{"slug": "introducing-marimo-studio", "title": "Introducing marimo-studio", "summary": "The marimo team released marimo-studio, an open-source tool that lets a single marimo notebook power multiple audience-specific frontends in any web framework while keeping views in separate files from the analysis. Studio prerenders each view's states at build time so it runs as static files on hosts like GitHub Pages with no Python runtime, and every number on a page traces back to the notebook cell that computed it. The package ships with example notebooks including quadratic_program.py, athletes.py, and occupancy.py, whose views are built with React, Reveal.js, Svelte, Mosaic, Three.js, and Observable Notebook Kit.", "body_md": "# Introducing marimo-studio\n\nBuild a view of your notebook for every audience, in any web framework, with every result traced back to the Python behind it.\n\nYour marimo notebook is where your computational work lives: the data, the definitions, and every assumption behind a result. Each audience you share it with has different needs and expects an experience tailored to them: a lecture for students, an article for readers, a dashboard for your team.\n\nToday we’re introducing\n[`marimo-studio`](https://github.com/marimo-team/marimo-studio), which gives\neach audience its own view of the notebook:\n\n- **Any frontend.** Each view is its own web project, in whatever framework you\nlike.\n- **Separate files.** Views live next to the notebook, so coding agents build\nthem without editing your analysis.\n- **Traceable results.** Every number on a page traces back to the notebook\ncell that computed it.\n- **Prepared static exports.** Studio prerenders a view’s states at build time,\nso it runs as static files on GitHub Pages or any host, with no Python runtime\nto load. Readers see the results and never the notebook source, which keeps\nsensitive work private.\n\nCopy this instruction for your coding agent to get started:\n\nYour agent reads the instructions Studio ships with the package, then builds a single notebook with the two requested views.\n\n## \n\nNotebooks usually reach their audiences in one of two ways. The first is a copy of the notebook for each audience. The copies drift: a fix made in one never reaches the others, and the slides end up disagreeing with the article.\n\nThe second is to put the presentation into the notebook, with HTML templates, CSS, and layout code in cells next to the calculations. The notebook gets harder to read and to review, because a font change and a formula change land in the same file.\n\nCoding agents make the second path more tempting. They write frontend code well, so a polished page is one request away. When the agent works inside the notebook, though, each design request also edits the file that holds your analysis. We wanted agents to take on the frontend work while the analysis stays put, so Studio keeps the two in separate files.\n\n## \n\nNotebooks do all kinds of work. Some teach an idea, some dig through data, and some explain how a model behaves, and one notebook often has to serve several kinds of readers at once. With Studio, the same notebook serves every one of them.\n\n### \n\n[`quadratic_program.py`](https://github.com/marimo-team/marimo-studio/blob/72376de50eb89fe8372ad55f3b341cfb439be154/examples/quadratic_program.py) teaches quadratic programs, a kind of optimization\nproblem. The same notebook becomes a slide deck for the lecture, an explainer\nto read at your own pace, and a lab where you drag a dial and watch the\nsolution move.\n\nThe deck runs on React and [Reveal.js](https://revealjs.com/), the explainer\nis plain HTML, and the lab is a [Svelte](https://svelte.dev/) app.\n\n### \n\n[`athletes.py`](https://github.com/marimo-team/marimo-studio/blob/72376de50eb89fe8372ad55f3b341cfb439be154/examples/athletes.py) digs into the roster of the Rio 2016 Olympics. The same analysis\nopens as a report you can filter by sport, an explorer with linked charts, and\na 3D tour of every athlete.\n\nThe report is plain HTML, the explorer links its charts with\n[Mosaic](https://uwdata.github.io/mosaic/), and the tour runs on\n[Three.js](https://threejs.org/).\n\n### \n\n[`occupancy.py`](https://github.com/marimo-team/marimo-studio/blob/72376de50eb89fe8372ad55f3b341cfb439be154/examples/occupancy.py) predicts whether a room is occupied from its sensor readings.\nThe same model shows up as a monitor of the room, a review where you move the\ndecision threshold and watch the errors change, and a report you can download\nas a PDF.\n\nThe monitor is an [Observable Notebook\nKit](https://observablehq.com/notebook-kit/kit) page, and the review and the\nreport are React apps.\n\nThe [examples gallery](https://marimo-team.github.io/marimo-studio/examples/)\nhas more.\n\n## \n\nEach view is an ordinary frontend project, saved as a folder next to the notebook. A coding agent works with its HTML, components, and build config the same way it would in any web project:\n\nStudio builds plain HTML, React, Svelte, and Observable Notebook Kit projects\nout of the box, and a [provider\nAPI](https://marimo-team.github.io/marimo-studio/reference/provider-api)\nconnects any other frontend project and its build command. Preview rebuilds on\nevery save, so you can watch a view take shape and steer it as you go.\n\n## \n\nInside a view, two elements and one attribute reach into the notebook by name:\n\n| In the view | What the page gets | \n|---|---|\n| `<marimo-cell>` element | A cell’s output, with live controls | \n| `<marimo-output>` element | One object, even one the notebook never shows | \n| `mo-value` attribute, on any element | One value, as data for the page’s own code | \n\nViews can lean either way. The Explainer mostly places the notebook’s own cells,\nwhile the Lab reads values and draws nearly everything itself with Svelte and\n[D3](https://d3js.org/).\n\n### \n\nEach figure and number a view shows comes from one named notebook cell. When you change a control in a view, marimo reruns the cells that depend on it and the view updates, so every view agrees with the notebook.\n\nThe same link makes every result in a view auditable. Studio resolves each name\nto the cell that produces it, and marimo’s [dataflow\ngraph](https://docs.marimo.io/guides/editor_features/dataflow/) leads from that\ncell to the data, definitions, and assumptions behind it. A reviewer checks a\nnumber on the page by reading the Python that computes it, and\n`marimo-studio validate` reports any name a view uses that the notebook no\nlonger defines.\n\n### \n\nValues reach the page through standard DOM events. `mo-value` sets\n`marimoValue` on its element and dispatches `marimo-value-updated` each time\nthe notebook recomputes the value, so any page can listen for it:\n\nThe React and Svelte starters wrap the same events for you: React views get a\n`useMarimoValue` hook, and Svelte views a `use:observeMarimoValue` action.\n\n## \n\nA view can be shared as a folder of static files on GitHub Pages or any other\nstatic host. You choose how the exported view runs. A browser export runs\nthe notebook in each visitor’s browser with [Pyodide](https://pyodide.org/), a\nbuild of Python for WebAssembly. A prepared export runs no Python at all, on a\nserver or in the browser.\n\nPrepared exports are new, and\n[`marimo-export`](https://github.com/marimo-team/marimo-export) powers them.\nStudio runs the notebook ahead of time for the control settings a view lists\nand saves each result as static files. Visitors move between those saved\nstates, and the notebook source stays with you. Every view on this page is a\nprepared export. We’re excited to share more about the approach, and how it\nbuilds on marimo’s cell cache, in an upcoming post.\n\nWhen a notebook needs live Python, for example to read files on a server, use\ncredentials, or call a service, `marimo run` serves the same view from a Python\nserver.\n\n## \n\nPython app frameworks such as [Streamlit](https://streamlit.io/) and\n[Reflex](https://reflex.dev/) let you build an interactive app by writing its\ninterface in Python. Frontend-first tools such as\n[Observable Framework](https://observablehq.com/framework/) and\n[Evidence](https://evidence.dev/) start from the page, and pull in the data it\nneeds from scripts or queries.\n\nStudio sits between an ordinary marimo notebook and the frontend ecosystem that already exists, and it turns the frontend-first order around. The notebook is the center. It holds the analytical context, the decisions and knowledge its author builds up: where the data comes from, how each number is defined, and which assumptions a model makes. Like a semantic layer, it defines what the numbers mean, and every view reads from it.\n\n[Malloy](https://github.com/malloydata/malloy) and\n[Malloyyo](https://github.com/malloydata/malloyyo) take a similar approach, with\nagents building dashboards over a semantic model written in Malloy. In Studio,\nthe context lives in a marimo notebook written in Python and SQL, and views can\nuse any frontend framework.\n\nThis fits how coding agents already work. They write good Python in notebooks and good frontend code in web projects, and Studio lets them do each where it belongs, with no new app framework to learn. As agents make views inexpensive to build, the analytical context behind them is worth more, and Studio keeps that context in one notebook that grows with every change its author makes.\n\n## \n\nThe notebook behind every view is a regular marimo notebook, so everything built\nfor marimo keeps working with it. It runs in a\n[sandbox](https://docs.marimo.io/guides/package_management/sandboxes/) with its\nown dependencies, serves as an app, and pairs with your coding agent through\nmarimo’s AI sidebar or `marimo pair`.\n\n[`marimo-lens`](https://marimo.io/blog/introducing-marimo-lens) shows what this makes possible. Select\npart of a page, describe a change, and Lens hands your agent the selection, your note,\nand the notebook cells behind it. With Studio, Lens works in the notebook and\nin every view, so the agent can tell whether a change belongs in the view or in\nthe notebook.\n\nIn the recording, restyling a table changes only the view. Labeling the figure changes the notebook, and the label appears in both at once.\n\n## \n\nStudio is available on PyPI as `marimo-studio`. The\n[documentation](https://marimo-team.github.io/marimo-studio/) walks through\n[a first view](https://marimo-team.github.io/marimo-studio/guide/getting-started),\n[authoring with a coding agent](https://marimo-team.github.io/marimo-studio/guide/coding-agents),\nand [running or exporting a view](https://marimo-team.github.io/marimo-studio/guide/run-and-share).\n\nIf something breaks or you have an idea, please\n[open an issue](https://github.com/marimo-team/marimo-studio/issues).\n\nOn a personal note, before I started developing marimo itself, I was a user\ndeveloping **with** marimo. One of the things that drew me to it was that a\nnotebook could also be an interactive web app. I still\nvalue that. But the more notebooks I wrote, the clearer the gap became between\nthe interface I need as the author and the one the people reading my notebooks\nactually want to use.\n\nStudio is my answer. Each reader gets a page made for them, and the notebook stays the place where I work, a regular marimo notebook ready for whatever marimo adds next. I can throw away any view without throwing away the attention I invested in the analytical context that produces it.", "url": "https://wpnews.pro/news/introducing-marimo-studio", "canonical_source": "https://marimo.io/blog/introducing-marimo-studio", "published_at": "2026-10-01 00:00:00+00:00", "updated_at": "2026-10-01 11:46:32.653678+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools"], "entities": ["marimo", "marimo-studio", "GitHub Pages", "React", "Reveal.js", "Svelte", "Mosaic", "Three.js"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/introducing-marimo-studio", "markdown": "https://wpnews.pro/news/introducing-marimo-studio.md", "text": "https://wpnews.pro/news/introducing-marimo-studio.txt", "jsonld": "https://wpnews.pro/news/introducing-marimo-studio.jsonld"}}