Streamlit + Wasm + Electron = Desktop app!

As a part of the stlite project (a forum post), I created a toolkit to package your Streamlit app into a standalone desktop app with Electron.

Follow the instruction at stlite/packages/desktop-cli at main · whitphx/stlite · GitHub !


A sample app repository
Distributable files (the macOS app file is not signed, so the security alert may be shown)

@Charly_Wargnier’s tweet on it (thanks!):

It’s just been published, so please let me know if you find some errors.

Thanks!

22 Likes

This is really cool!

Do you have any idea if performance is increased on a Streamlit desktop app? The only major drawback for using Streamlit for me personally is that it can’t display things quickly like PyQT might be able to.

For example, would playing a video be faster? Can streamlit display 60 fps video from frames?

1 Like

Thanks!

Does the “performance” here means the frame rate?
If so, I think the answer is no, same as the answer at the linked thread. Even with stlite, both the server and the frontend app are the same to original Streamlit, so the situation does not change.

2 Likes

This is awesome!
Fantastic work!
Thank you!

2 Likes

Really nice idea & implementation! Do I understand it right that we so far only talk about apps for macOS (so no Windows and Linux)?

1 Like

Thanks!

No, there is already Windows and Linux support, though personally I have not tested it on my local env.

As written in the README, this desktop app bundler is just using Electron and electron-builder that can create executables for Windows, macOS, and Linux.

1 Like

Uh, nice! Ok, I really need to give it a try! :+1:

2 Likes

Hi, Thank you for sharing. How to manage virtual environnement with Electron app please ?
I’m running on windows 11… I’m also interrested on linux @whitphx

1 Like

@NotAfk Although I’m not sure about what you actually want,
with stlite, there is not virtual environment concept and we don’t need to consider about it anyway.
On stite (Pyodide), the Python runtime is sandboxed in the web browser’s JS environment and created every time the app launches.

1 Like

Hi! :bouquet:
Thanks for sharing this awesome app!
Do these electron builds remain offline for the end user? Like - Can they use the Electron-built streamlit app with no internet connection and with no connection to a server on my end? If this is the case, you’ve solved a half-year struggle!

1 Like

@Sebastian_S_Engen Hi, thanks.
Yes, it is one of the main purposes of stlite desktop app bundler.

2 Likes

@whitphx :love_you_gesture: wow, thanks for creating and sharing this.
I really hope to see further development, I don’t think native streamlit apps are part of the current roadmap.

Is it possible to change the python version ? Or is this utterly dependent on Pyodide and pure Python wheels for 3.10

1 Like

@flight505 Hi, thanks!

The Python version is fixed and cannot be changed.

As you said, it is because the fixed version of CPython is built in the Pyodide runtime. For example, Pyodide 0.21 has only Python 3.10 Python 3.10 by hoodmane · Pull Request #2225 · pyodide/pyodide · GitHub

2 Likes

Hi @whitphx,

Thank you for taking the time to create the app bundle.
With your instructions, I comfortably bundled my first Streamlit desktop app.

I am currently trying to persist an offline database - in my case a json file - and am following some instructions I found online: Stackoverflow Question.

The first step is to add an “extraResource” key to the package.json file and have the value be the resource location once bundled.

The next instruction is to add the following code into what is likely the main.js file (found in the “build / electron” directory) so that you can potentially reference the resource from within app once bundled.

const configFile = path.join(path.dirname(__dirname), 'extraResources','config.json');

I’m not much of a JS guy, and am wondering if you have any advise or experience setting up an offline database for an electron app? I’ve thought about adding the above code in to the main.js file but cannot logically understand where it would go.

It should be noted that I have managed to push the database file into the dist folder with the “npm run dist” command, but I am unable to locate it from within the bundled app.

file path: dist / win-unpacked / resources / extraResources / data.json

I’ve also kept the database file within the streamlit_app directory, but it obviously resets when you shut down the app and restart again.

Many Thanks, Jason

1 Like

@JasonPython

Hi, thank you for trying it out.
Unfortunately it does not support persisting data or file changes now.

I have managed to push the database file into the dist folder with the “npm run dist” command, but I am unable to locate it from within the bundled app.

So this is an expected behavior that only the contents in the streamlit_app directory are loaded to the app, and changes on these files are never persisted.

I created an issue about this, so please track it:

1 Like

Hi @whitphx ,

I appreciate you for getting back to me - will track the issue you raised and post anything I manage to uncover in the mean time.

Thank you, Jason

2 Likes

Hi @whitphx this is awesome and I love the idea.
But unfortunately it’s not working good for me because there is a version incompatibility between Streamlit and Altair versions. Could someone help me?

Thank you.

1 Like

@carlosanpa00 Hi, is it this issue? If so, there is a solution posted in the issue thread.

Thanks!

1 Like

@whitphx : you rock, thank you for making this wrapper.

Does anyone know a resource that would explain howto handle requests with it? I know requests package won’t do the trick (not implemented in Pyodide).

I’d like to fetch the data from the website using its API, then create object using this fetched data. So far my experiments with pyodide.http.pyfetch failed miserably as I got TypeError: coroutine object is not subscriptable.

1 Like

@Przemek Thank you!
This section in the README may help.
I think you used pyodide.http.pyfetch without await then got that error.

1 Like