New library: stlite, a port of Streamlit to Wasm, powered by Pyodide

Hi, I started versioned releases and publishing an NPM package, so now the script can be loaded from the jsDelivr CDN with a version-pinned URL as below.
So I have removed the warning from the README saying stlite might be broken or the API might change without any notice. It never happens now as long as we use the pinned URL.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>stlite app</title>
</head>
<body>
  <div id="root"></div>
  <script src="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.1.0/build/stlite.js"></script>
  <!-- 👆👆👆 New URL! 👆👆👆 -->
  <script>
    stlite.mount(`
import streamlit as st

name = st.text_input('Your name')
st.write("Hello,", name or "world")
`,
    document.getElementById("root"))
  </script>
</body>
</html>

The URL starting with https://whitphx.github.io/stlite/ that has been used in some old examples is now recommended not to use.

Please check out the updated README :smiley:

(BTW, I created a logo ↑ :v:)

1 Like

Multipage apps (MPA) are supported!

The playground app has been updated to be an MPA too.

You can mount multiple files including pages/*.py as below.

stlite.mount(
  {
    entrypoint: "👋_Hello.py",
    files: {
      "👋_Hello.py": `
import streamlit as st

st.set_page_config(page_title="Hello")
st.title("Main page")
`,
      "pages/1_⭐️_Page1.py": `
import streamlit as st

st.set_page_config(page_title="Page1")
st.title("Page 1")
`,
      "pages/2_🎈_Page2.py": `
import streamlit as st

st.set_page_config(page_title="Page2")
st.title("Page 2")
`,
    },
  },
  document.getElementById("root")
);

I am developing the online code editor for stlite.

editor screenshot

I created the dedicated post for it :slight_smile:

1 Like

I created a desktop app toolkit for stlite.
Here is the thread about it :slight_smile:


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

1 Like

This is a great tool! Do you have a list of packages that are compatible with stlite? I’ve tried a few like millify, sklearn and pdfkit but they didn’t work.

Thank you!

In short, please see Packages built in Pyodide — Version 0.21.3


The installable packages are

  1. Pure Python packages (packages that do not include C code).
  2. C extensions compiled for the Pyodide runtime.

The linked page is the list for 2.

There is no complete list for 1.
You can only check the availability of each package by checking if the distributed package file name ends with “py3-none-any.whl”.
For example, semver package is installable because its file name is semver-2.13.0-py2.py3-none-any.whl as found at the PyPI package that ends with “py3-none-any.whl”.

Hello,
thank you for your Work! That is really awsome!

Is it possible to refer to other files or folders?

For example reference the file to start the streamlit app?

Thank you!

For example:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <title>stlite app</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.15.0/build/stlite.css"
    />
  </head>
  <body>
    <div id="root"></div>
    <script src="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.15.0/build/stlite.js"></script>
    <script>
      stlite.mount(
  {
    entrypoint: "streamlit_app.py", // The target file of the `streamlit run` command
    files: {
      "streamlit_app.py": 
      `
#refere to home.py file
import home

#execute main()
home.main()
    `,
    },
  },
  document.getElementById("root")
);
    </script>
  </body>
</html>
1 Like

Just add home.py to the files option in addition to streamlit_app.py like


stlite.mount(
  {
    entrypoint: "streamlit_app.py",
    files: {
"streamlit_app.py": `import home

home.main()
`,
"home.py": `import streamlit as st

def main():
    st.write("Hello")`,

},
  },
  document.getElementById("root")
)

Sample: stlite sharing

The multipage app example can also be a sample with folders: GitHub - whitphx/stlite: Serverless Streamlit

Hi,

Thank you!
I have successfully added a streamlit app to my webpage using stlite according to your example.
But it takes over the entire page. I would prefer to keep my own (for example bootstrap) navbar and add some descriptive text before the app.
Is there an easy way to do this?


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>stlite app</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
    <!-- I would like to add my navbar and other html elements here before the streamlit app  -->
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="collapse navbar-collapse" >
            <div class="navbar-nav">
                <a class="nav-item nav-link active" href="#">Home</a>
                <a class="nav-item nav-link" href="#">Features</a>
            </div>
        </div>
    </nav>
    <div class="container">
        <p>Description</p>
    </div>
    <!-- end of example html elements to add-->

    <div id="root"></div>
    <script src="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.15.0/build/stlite.js"></script>
    <script>
    stlite.mount(`
import streamlit as st

name = st.text_input('Your name')
st.write("Hello,", name or "world")
`,
    document.getElementById("root"))
    </script>
</body>
</html>

At this moment, the full-screen behavior is inevitable as it’s an intended design by Streamlit.

One option may be to create the stlite app in another page and embed it to the main page with iframe.
How is it?

Thank you for the reply and suggestion. I will do that :slightly_smiling_face:

Hello,
I confirm that this code is working

import pyodide
raw_data = pd.read_csv(pyodide.open_url(data_url))

Still doesn’t know how to read a non text file like an image or .joblib.
Outstanding work btw!

Thank you.

It seems to be not possible now, sorry.

The download of binary files is not supported.
pyodide.http — Version 0.22.1

One workaround is, if you are using @stlite/mountable like this example on README, to download the file outside stlite and pass it to the files option of stlite.mount() so that the app can access the file on the virtual local file system.

I opened the issue about it: Provide a way to download binary files · Issue #511 · whitphx/stlite · GitHub
So please track it.

Thank you!

1 Like

hi,
is it possible to acces a csv file in a github private repository?
for public repositories, this code actually works

import pyodide
raw_data = pd.read_csv(pyodide.open_url(data_url))

also, i can acces the csv file in a private repo locally using a personal access token, here is the code

import requests 
github_session = requests.Session()
github_session.auth = (username, token)
url = "csv_url"
download = github_session.get(url).content
df = pd.read_csv(io.StringIO(download.decode('utf-8')))

but when trying it with stlite i get a connection error
image

my second question is :
Since the data file and the streamlit page are in the same repo, is it possible to access the files just using a relative path/reference (“data/file.csv”) instead of accesing via web url ?

nb : i am using github entreprise

@s.mounji

@Abdelgha_4
I released v0.29.0, which allows us to use pyodide.http.pyfetch() with top-level awaits as described in the README as GitHub - whitphx/stlite: Serverless Streamlit.

The charts.audio example in the “Component Gallery” sample app actually uses it as below

1 Like