• Stars
    star
    1,138
  • Rank 40,819 (Top 0.9 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created over 2 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

In-browser Streamlit ๐ŸŽˆ๐Ÿš€

stlite: Serverless Streamlit

Test, Build, and Publish Build and Deploy GitHub Pages

npm (@stlite/kernel) npm (scoped) npm (@stlite/desktop)

A port of Streamlit to WebAssembly, powered by Pyodide.

Streamlit is a Python web app framework for the fast development of data apps. This project is to make it run completely on web browsers.

Try it out

Visit stlite sharing.

Create a desktop app

See @stlite/desktop.

Use stlite on your web page

You can use stlite on your web page loading the script and CSS files via <script> and <link> tags as below. Here is a sample HTML file.

<!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/[email protected]/build/stlite.css"
    />
  </head>
  <body>
    <div id="root"></div>
    <script src="https://cdn.jsdelivr.net/npm/@stlite/[email protected]/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>

In this sample,

  • stlite library is imported with the first script tag, then the global stlite object becomes available.
  • stlite.mount() mounts the Streamlit app on the <div id="root" /> element as specified via the second argument. The app script is passed via the first argument.

More controls

If more controls are needed such as installing dependencies or mounting multiple files, use the following API instead.

stlite.mount(
  {
    requirements: ["matplotlib"], // Packages to install
    entrypoint: "streamlit_app.py", // The target file of the `streamlit run` command
    files: {
      "streamlit_app.py": `
import streamlit as st
import matplotlib.pyplot as plt
import numpy as np

size = st.slider("Sample size", 100, 1000)

arr = np.random.normal(1, 1, size=size)
fig, ax = plt.subplots()
ax.hist(arr, bins=20)

st.pyplot(fig)
`,
    },
  },
  document.getElementById("root")
);

Various ways to load files

You can pass an object to the files option to mount files, whose keys are file paths, and you can specify the values in various ways as below.

Passing string or binary data

You can pass the file content as a string or binary data.

This is what we did in the example above.

stlite.mount(
  {
    files: {
      "path/to/text_file.txt": "file content",
      "path/to/binary_file.bin": new Uint8Array([0x00, 0x01, 0x02, 0x03]),
    },
    // ... other options ...
  },
  document.getElementById("root")
);

Passing an object with a URL

You can use this way to load a file from a URL and mount it to the specified path on the virtual file system.

Either an absolute or relative URL is accepted. Consider as the same as the url option of the fetch() function.

stlite.mount(
  {
    files: {
      "path/to/file": {
        url: "https://example.com/path/to/file",
      },
      "path/to/file2": {
        url: "./path/to/file",
      },
    },
    // ... other options ...
  },
  document.getElementById("root")
);

Passing an object with options (advanced)

stlite runs on Pyodide, and it has a file system provided by Emscripten. The files specified via the files option are mounted on the file system, and Emscripten's FS.writeFile() function is used internally for it. You can specify the options (opts) for the FS.writeFile(path, data, opts) function as below.

stlite.mount(
  {
    files: {
      "path/to/text_file.txt": {
        data: "file content",
        opts: {
          encoding: "utf8",
        },
      },
      "path/to/file": {
        url: "https://example.com/path/to/file",
        opts: {
          encoding: "utf8",
        },
      },
    },
    // ... other options ...
  },
  document.getElementById("root")
);

Loading archive files

You can load archive files such as zip files, unpack them, and mount the unpacked files to the file system by using the archives option.

The url field of each item accepts either an absolute or relative URL. Consider as the same as the url option of the fetch() function.

The downloaded archive file is unpacked by the pyodide.unpackArchive(buffer, format, options) function. You have to pass the rest of the arguments of the function, format and options as below.

  mount(
    {
      archives: [
        {
          url: "./foo.zip",
          // buffer: new Uint8Array([...archive file binary...]), // You can also pass the binary data directly
          format: "zip",
          options: {},
        },
      ],
      // ... other options ...
    },
    document.getElementById("root") as HTMLElement
  );

Other stlite versions

In the example above, the stlite script is loaded via the <script> tag with the versioned URL. You can use another version by changing the version number in the URL.

The following URLs are also available, while our recommendation is to use the versioned one as above because the API may change without backward compatibility in future releases.

The latest release

<script src="https://cdn.jsdelivr.net/npm/@stlite/mountable/build/stlite.js"></script>

You can use the latest version of the published stlite package with this URL.

The head of the main branch

<script src="https://whitphx.github.io/stlite/lib/mountable/stlite.js"></script>

This URL points to the head of the main branch which is usually ahead of the released packages. However, we strongly recommend NOT to use this URL because this might be broken and there is no guarantee that this resource will be kept available in the future.

Multipage apps

You can pass the multiple files to the files option as below to construct the multipage app structure, the entry point file and pages/*.py files.

Read the Streamlit official document about the multipage apps.

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")
);

Limitations

As stlite runs on the web browser environment (Pyodide runtime), there are things not working well. The known issues follow.

Other problems are tracked at GitHub Issues: https://github.com/whitphx/stlite/issues If you find a new problem, please report it.

Top-level await

TL;DR: use top-level await instead of asyncio.run() on stlite.

Unlike the original Streamlit, stlite supports top-level await due to the differences in their execution models. Streamlit runs in a standard Python environment, allowing the use of asyncio.run() when an async function needs to be executed within a script. In contrast, stlite runs in a web browser, operating in an environment where the only event loop is always in a running state. This makes it impossible to use asyncio.run() within a script, necessitating the support for top-level await.

Top-level await can be useful in various situations.

Example 1: asyncio.sleep()

One of the most common use cases is asyncio.sleep(). As mentioned in the previous section, time.sleep() is no-op on stlite because its blocking nature is not compatible with the single-threaded event loop in the web browser environment. Instead, asyncio.sleep(), which is non-blocking, can be used to pause the execution of a script for a specified amount of time.

You can use top-level await either for asyncio.sleep() directly or for an async function that contains asyncio.sleep() like the following:

import asyncio
import streamlit as st

st.write("Hello, world!")
await asyncio.sleep(3)
st.write("Goodbye, world!")
import asyncio
import streamlit as st

async def main():
    st.write("Hello, world!")
    await asyncio.sleep(3)
    st.write("Goodbye, world!")

await main()

Example 2: pyodide.http.pyfetch()

Another common use case is accessing external resources. In the Pyodide environment, widely-used URL access methods in Python, like requests, are not available. However, Pyodide provides pyodide.http.pyfetch() as an alternative for accessing external resources. Since this method is async, top-level await becomes handy for utilizing pyodide.http.pyfetch().

Here's a sample code snippet demonstrating the usage of top-level await with pyodide.http.pyfetch():

import pyodide.http

url = "your_url_here"
response = await pyodide.http.pyfetch(url)
data_in_bytes = await response.bytes()

Resources

Samples

โšก๏ธServerless Image Processing App

Image processing with OpenCV works on the client-side.

See the tutorial video

Serverless Streamlit + OpenCV Python Web App Tutorial, crafted by 1littlecoder.

Serverless Streamlit + OpenCV Python Web App Tutorial

Sponsors

Streamlit (Snowflake)

Databutton

They are sponsoring me on GitHub Sponsors!

Hal9

They are sponsoring me on GitHub Sponsors!

Support the project

ko-fi

Buy Me A Coffee

GitHub Sponsors

Contact the author: Twitter / LinkedIn.

More Repositories

1

streamlit-webrtc

Real-time video and audio streams over the network, with Streamlit.
Python
1,348
star
2

vscode-emacs-mcx

Awesome Emacs Keymap - VSCode emacs keybinding with multi cursor support
TypeScript
367
star
3

streamlit-stt-app

Real time web based Speech-to-Text app with Streamlit
Python
213
star
4

streamlit-webrtc-example

Real time video and audio processing examples with Streamlit and streamlit-webrtc
Python
144
star
5

streamlit-server-state

A "server-wide" state object shared across sessions on a Streamlit server.
Python
129
star
6

lear-gist-python

A python wrapper for Lear's GIST implementation working with numpy
C
55
star
7

transformers.js.py

TypeScript
55
star
8

streamlit-component-template-react-hooks

Streamlit component lib with React hooks and template project using it
TypeScript
52
star
9

react-ymd-date-select

Hooks and components for Y-M-D dropdowns with React
TypeScript
45
star
10

streamlit-video-chat-example

Video chat apps with computer vision filters built on top of Streamlit
Python
42
star
11

stlite-image-processing-app

Serverless OpenCV image manipulation app with Streamlit
HTML
31
star
12

streamlit-fesion

TypeScript
18
star
13

streamlit-webrtc-article-tutorial-sample

Python
16
star
14

ReactCrossDeviceTodoExample

Sample app running on iOS / android / web (+ electron) using React, React native, Redux
JavaScript
15
star
15

stlite-desktop-example

Python
12
star
16

streamlit-theme-editor

Python
11
star
17

fastapi-typescript-openapi-example

TypeScript
10
star
18

tiny-streamlit-webrtc

Python
7
star
19

react-redux-pouch-example

Sample project using react, redux, react-router and pouchdb
JavaScript
7
star
20

quarto-stlite

Lua
5
star
21

randomstring-promise

Random string generator with promise interface for nodejs, browsers, and react-native
JavaScript
4
star
22

text-classification-app-example

Text classification server written in python (Flask, scikit-learn) and its interface using Vue.js
Jupyter Notebook
3
star
23

fuel-kana

ๆ—ฅๆœฌ่ชžใฎใƒ•ใƒชใ‚ฌใƒŠใ‚’HTMLใง่กจ็พใ™ใ‚‹ใŸใ‚ใฎ<ruby>ใ‚ฟใ‚ฐใ‚’ๅ‡บๅŠ›ใ™ใ‚‹ใƒ˜ใƒซใƒ‘ใƒผ
PHP
3
star
24

whitphx.info

TypeScript
2
star
25

risk-assessment-long-term-investment

Python
2
star
26

stlite-sample

Python
2
star
27

streamlit-appengine-samples

Dockerfile
2
star
28

europython2022-streamlit-webrtc-example

Python
2
star
29

europython2022-streamlit-webrtc

2
star
30

pycon2024-streamlit

1
star
31

stlite-desktop

1
star
32

streamlit-webrtc-hugging-face-transformer-example

Python
1
star
33

csv-to-md

CSV to Markdown converter https://tuttieee.github.io/csv-to-md/
JavaScript
1
star
34

kms7-decoder-bug-example

TypeScript
1
star
35

gstreamer-python-sample

Python
1
star
36

asha-nepal

CSS
1
star
37

europython2022-streamlit-webrtc-example-predeploy

Python
1
star