Skip to main content

Inside Fused Apps: Python in The Browser

· 8 min read
Isaac Brodsky
CTO @ Fused
Max Lenormand
Developer Advocate @ Fused

This is a technical deep dive into how we built Fused Apps, a way to build a Python-based workflow in your browser, that you can save and share with someone. You can read the full product announcement here.

At Fused, we’re building tools to help data scientists work more efficiently: we want to give them the ability to work on any dataset, create an analysis and scale it to the whole world with just a few lines of code. But data scientists don’t work in a vacuum, and analysis aren’t (always) done because people are simply curious about a topic.

We built Fused Apps in the spirit of allowing a single person to do all the work themselves; and in this first episode of Inside Fused, a series of blogposts about how we’re building Fused, we want to take you behind the curtain to show how Fused Apps is built.

Fused Apps at a glance

Fused provides both a Python package to run User Defined Functions (UDFs), and Workbench, a browser-based IDE to write, execute, visualize them as well as create Fused Apps to make interactive frontends.

Here’s what Fused Apps look like:

Fused apps preview

Fused Apps. From left to right: the list of apps that have been loaded in Workbench, the app code editor, and the running app itself.

The App code editor & renderer allow users to write their own Python code using Streamlit to build a frontend entirely in Python, a language most data scientists already work with.

We want data scientists to be able to go from “hey, that’s a cool idea” to “here’s what it looks like” without tech getting in their way. Especially in a world where LLMs make writing code simpler, the bottleneck becomes the speed at which data scientists can execute & ship code, not write it.

Fused Apps offers a way for data scientists to orchestrate their entire workflow using Python, without having to worry about backends, scaling, or clusters. Fused Apps complement our UDF builder, which offers a way to build data processing and backend functions, by offering an end-to-end workflow. At Fused, we use this for ingesting and managing datasets, managing resources we make available to our UDFs, and finalizing analyses.

Fused Apps work on any device, as long as there's a browser!

How we built it

In short, Fused Apps tie together a frontend application for users to write Python code with Streamlit, a backend that saves & serves these apps and provides shareable links, and a product experience tying all of this together (error handling, autocomplete suggestions, async UI functionalities, etc.)

Fused Apps are built on top of Stlite & Streamlit. Streamlit being a library allowing you to write a frontend application, entirely in Python, and Stlite an in-browser version of Streamlit. This allows people familiar with Python but not so much frontend development (like data scientists) to have something rendered on screen in HTML, but only with writing Python.

Stlite provides the ability to run apps in the browser, and while Stlite Sharing does support URL-encoded mechanisms for app sharing, the URL is the same as the code, preventing users from updating said code; there’s also no such thing as app catalogs, etc. So we ended up using Stlite as the engine and built a product experience around that.

The frontend for building a Python-in-the-browser application already exists, with Streamlit & Stlite. However the backend had to be built from the ground up.

Originally, we didn’t even have a way for people to save their apps! Our internal workflow while developing & testing this was to have a Slack channel where we pasted our app links in to be able to find them later on

Early days Slack sharing links

This is at the the core of our development philosophy: Build a prototype, use it a bunch, find the pain points, fix them, build more. In this case, saving & tracking apps was the next piece to build.

This is how we added functionality like Github integration, sharing options, and an app catalog. All these were only added after we got some traction internally and from early customers.

Sharing Fused Apps is just a couple of clicks now

Python, in the browser

The next piece of this puzzle is to realise that running Python locally on your machine and in the browser is quite different. We want to make the experience for the user as seamless as possible: we’re building products for data scientists to build everything in Python.

We use Pyodide to run Python in WASM. This enables the same Python language to be used in a new environment – the browser. The browser environment is key because it gives us a way to safely ship applications to users.

Safely shipping software to people wasn’t always the simplest. Previous efforts via Flash and Java applets enabled a generation of rich web content. The promise of Java applets was run anywhere – that the same code could run on anyone’s computer. These technologies died out mainly because of security model problems. (Java lives on in Blu-ray disks.)

At the time of writing this, in mid 2025, browser applications are considered well sandboxed (with the possible exceptions of RowHammer/Spectre type issues), browser applications open when you want them, and go away completely when you dismiss them, all the while performing more and more complex tasks. Browser applications handle video encoding/decoding for video conferencing, graphics rendering for games, maps, and design, and more frequently, for programming. Companies like Figma are building complex, professional grade applications for the browser first.

From a development perspective, the browser becomes an operating system. It becomes less important to know what exact hardware & underlying operating system the users have, and we develop applications for the browsers’ APIs. Those applications are inherently portable to new devices, because the heavy lifting is porting the browser to these new devices.

Building a Product

There are other projects out there that allow building hosted Stlite applications, however these miss some of the features that people expect from a well rounded product. Here are few things we’ve added to Fused Apps:

  • Package Handling (Every Fused Apps comes with fused and pyarrow pre-installed)
  • Error handling
  • Naming & saving of Apps
  • Github integration for teams
  • Creating shareable links allowing users to send their apps to anyone with a browser

Beyond the technical challenges we want to build a product that helps data scientists build, iterate and ship faster. A data scientist can build an analysis that takes in different parameters and make an interactive graph for their project manager to test out directly all without needing support

A big part of this is the philosophy of how we build things at Fused: We’re a team of engineers & data scientists. A lot of the features we’re listing above here come directly from our own usage of Fused Apps while making real applications with some of our customers.

We care about how fast it takes for a new user to click on a Fused App and start running it, or what the experience of saving & sharing an app looks like.

Every Fused App comes with some packages pre-installed, such as fused and pyarrow, which are helpful for data scientists. (Streamlit comes with a number of other common packages like Pandas and NumPy already.) But this comes at the expense of loading time, as each new app is a self-contained application which requires downloading all the required packages. This is leading us to spend time optimizing the initial loading time of Pyodide.

What can we expect from Pyodide

Fused Apps, and any implementation of Python in the browser, isn’t as customizable as a fully local setup. Packages with native code that are not prebuilt for WASM will not work. At the time of writing, some popular packages like Pandas & Numpy are built and supported, but others aren’t. The backbone of the map processing pipeline, GDAL, for example, isn’t currently supported. This isn’t from lack of popularity, but reflects the complexity of building GDAL.

Some packages will need architecture updates. As another example people currently call into ffmpegfrom Python using the CLI. The WASM environment does not have a CLI concept, and this would need to be replaced with library calls. Other packages which are not well suited to this architecture (such as Torch) might have alternatives developed because the wasm ecosystem is so attractive a development target.

LLMs in the Browser

An example of this is transformers.js.py. This library (developed by Yuichiro Tachibana, also behind Stlite) needed more than one level of architectural adaptation to get running in the browser, but once adapted it brought the capability of running lightweight LLMs. This allows us to ship applications that run small LLMs models, running locally in the browser!

We made a Fused App exploring the USDA’s Crop Data Layer (CDL) dataset, a dataset of different crop types in the US. Instead of showing all 130+ categories, we can just take a text input, run a similarity analysis on the fly against all the categories and find the closest CDL crop type!

CDL Bunnies

You too can find out what Bunnies prefer by trying this Fused App here

Compatibility & load times

This is a fast changing ecosystem though, for example we’ve made a small contribution of a build of the H3 package specifically because we wanted to have H3 supported in Python in the browser. The list of supported packages built in Pyodide is growing quickly.

Moving large amounts of data in and out of the browser is slow, so data-intensive libraries like Torch or Dask are not well-suited for this. We solve this by bringing in the compute performance & flexibility of Fused UDFs, which run native (non-WASM) Python in a cloud environment. Fused UDFs run code much closer to the data, improving performance, and are not limited by what packages are available for Pyodide, improving flexibility.

Install times for Pyodide are relatively long from a user point of view, as the application isn’t stored locally and installed each time it's opened. This will most likely keep improving over time as the technology is developed further. For example Pyodide wants to add memory snapshotting to help with this, but it isn’t stable yet.

Even when the application is stored locally, we found we needed to reinitialize Pyodide in some cases. There is no concept of switching virtual environments in Pyodide, since running a new script reuses the same Python VM. When switching between apps in Fused, we reinitialize Pyodide in order to prevent packages from one app interfering with another. If we didn’t do this, a user might accidentally rely on a package installed by App A in developing App B, which would then not work when sharing App B.

We also needed to be careful with when the app can run, since the app has access to the user’s browser context. We chose to give users the chance to inspect the app’s code before running it if it would have access to their Fused account.

Code written in Stlite and Pyodide looks almost the same as regular Python, but there are slight differences. Many of these come in the form of adapting synchronous and asynchronous code. Stlite for example allows for top-level await because the browser’s event loop is being used. This can be tricky to work with because regular advice for working around asynchronous code in Python does not work with Pyodide.

CDL loading async model & logging Async-aware UI allows us to provide improved feedback as an app loads a light weight LLM model or data to display

In order to create a good product experience, we added our own syntax checking and linting on top of Pyodide.

Error handling

Lots of small features go a long way to delighting users with a smooth experience.

Delivering at near-zero cost

Fused Apps are part of the free tier of Fused. You can use Fused Apps without logging in at all, and with a free login you can save and share your apps. We want to take a moment here to explain why this is naturally a free offering and will continue to be free.

As a browser-based application, all of the code execution and data transfer happens in the user's browser. This means that we do not need to sandbox code execution or pay for cloud compute resources to run anyone’s Fused Apps.

Where we do incur costs are in the shared control plane layer of Fused. Technically, the control place layer doesn’t see much difference between an app and a UDF. As a result, the incremental cost of serving an app user is very low and it is easy for us to offer that for free. The core offering of Fused is the backend serverless execution of code, which is our paid product.

Try it out for yourself

Don’t take our word for it, give Fused Apps a try for yourself! As we mentioned, Fused Apps are free and don’t require login. You can check out our catalog of public Apps in Fused Workbench.

Recently we announced re-partitioning the Crop Data Layer dataset into H3 hexagons for anyone to use and hosted the resulting dataset on Source Cooperative.

Alongside this we created a public Fused App allowing you to explore any crop for the 2024 dataset

We're hiring: Help us build the future of data science workflows!

We firmly believe data scientists need tools that give them the independence to do their work rather than asking for support to scale their analysis or share their results.

We need smart people to help us build all of this. We are hiring for:

  • Deep knowledge of Python & Pyodide
  • Opinionated thinking in building the future of data science pipelines
  • People wanting to join a fast moving startup and build things

If you’d like to join the team, send us your info here!

The team

Join the team!