0.54.2 • Published 9 days ago

@stlite/desktop v0.54.2

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
9 days ago

@stlite/desktop

Convert your Streamlit application into a desktop app with stlite runtime, a Pyodide-based Wasm-port of Streamlit.

How to create a Streamlit desktop app

  1. Create the following package.json file to start a new NPM project. Edit the name field.
    {
      "name": "xxx",
      "version": "0.1.0",
      "main": "./build/electron/main.js",
      "scripts": {
        "dump": "dump-stlite-desktop-artifacts",
        "serve": "cross-env NODE_ENV=production electron .",
        "pack": "electron-builder --dir",
        "dist": "electron-builder",
        "postinstall": "electron-builder install-app-deps"
      },
      "build": {
        "files": ["build/**/*"],
        "directories": {
          "buildResources": "assets"
        }
      },
      "devDependencies": {
        "@stlite/desktop": "^0.54.0",
        "cross-env": "^7.0.3",
        "electron": "^30.0.1",
        "electron-builder": "^24.13.3"
      },
      "stlite": {
        "desktop": {
          "files": ["app.py"],
          "entrypoint": "app.py"
        }
      }
    }
  2. Run npm install or yarn install.
  3. Create app.py and write your Streamlit app code in it. The file name app.py is specified both in the stlite.desktop.files field in the package.json and the stlite.desktop.entrypoint field. If you want to use a different file name, change the file name in both fields.
    • stlite.desktop.files specifies the files and directories to be copied to the bundled desktop app.
    • stlite.desktop.entrypoint specifies the entry point of the Streamlit app.
  4. You can add more files and directories, such as pages/*.py for multi-page apps, any data files, and so on, by adding them to the stlite.desktop.files field in the package.json.
    {
      // ...other fields...
      "stlite": {
        "desktop": {
          // ...other fields...
          "files": ["app.py", "pages/*.py", "assets"]
        }
      }
    }
  5. You can specify the packages to install in the desktop app by adding stlite.desktop.dependencies and/or stlite.desktop.requirementsTxtFiles fields in the package.json.
    • stlite.desktop.dependencies is an array of package names to install.
      {
        // ...other fields...
        "stlite": {
          "desktop": {
            // ...other fields...
            "dependencies": ["numpy", "pandas"]
          }
        }
      }
    • stlite.desktop.requirementsTxtFiles is an array of paths to requirements.txt files to install the packages listed in the files.
      {
        // ...other fields...
        "stlite": {
          "desktop": {
            // ...other fields...
            "requirementsTxtFiles": ["requirements.txt"]
          }
        }
      }
  6. Run npm run dump or yarn dump.
    • This dump command creates ./build directory that contains the copied Streamlit app files, dumped installed packages, Pyodide runtime, Electron app files, etc.
  7. Run npm run serve or yarn serve for preview.
    • This command is just a wrapper of electron command as you can see at the "scripts" field in the package.json. It launches Electron and starts the app with ./build/electron/main.js, which is specified at the "main" field in the package.json.
  8. Run npm run dist or yarn dist for packaging.
    • This command bundles the ./build directory created in the step above into application files (.app, .exe, .dmg etc.) in the ./dist directory. To customize the built app, e.g. setting the icon, follow the electron-builder instructions.

See the ./samples directory for sample projects.

Use the latest version of Electron

To make your app secure, be sure to use the latest version of Electron. This is announced as one of the security best practices in the Electron document too.

Configure the app

Hide the toolbar, hamburger menu, and the footer

If you want to hide the toolbar, hamburger menu, and the footer, add the following to your package.json file and run the dump command again. By adding the stlite.desktop.embed field, the dumped Streamlit app will work in the embed mode which hides the toolbar, hamburger menu, and the footer.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      "embed": true
    }
  }
}

File system

stlite runs your Python code on Pyodide, a CPython runtime compiled to Wasm, and Pyodide's backend, Emscripten, provides a virtual file system. When stlite runs your app, it mounts the source files onto the virtual file system, and what your Python code can access (e.g. open("/path/to/something")) is files and directories on the virtual file system.

The default file system (MEMFS) is ephemeral, so the files saved in the directories are lost when the app is restarted. If you want to persist the files across the app restarts, you can use the IndexedDB-based file system (IDBFS) or mount directories on the host OS file system to directories on the virtual file system.

File persistence with IndexedDB backend

You can mount the IndexedDB-based file system (IDBFS) to directories on the virtual file system that your Python code can access, e.g. open("/path/to/file"). You can specify the mount points via the stlite.desktop.idbfsMountpoints field in your package.json like below. Note that you have to run the dump command again to apply the change.

The mounted file system is backed by IndexedDB and its data is stored in the browser's IndexedDB, so the files saved in the directories are persistent across the app restarts.

In the example below, the IndexedDB-based file system is mounted to the /mnt directory on the virtual file system, so that the files saved in the directory are persistent.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      "idbfsMountpoints": ["/mnt"]
    }
  }
}

Local file access

You can mount directories on the host OS file system to directories on the virtual file system.

To do this, you have to enable the Node.js worker mode (see the next section for details) and specify the mount points via the stlite.desktop.nodefsMountpoints field in your package.json like below.

The nodefsMountpoints field is an object that maps the virtual file system paths to the host OS paths.

In the example below, "." on the host OS file system is mounted to the /mnt directory on the virtual file system, so your app can access the files in "." on the host OS by accessing the files in /mnt on the virtual file system.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      "nodeJsWorker": true,
      "nodefsMountpoints": {
        "/mnt": "."
      }
    }
  }
}

NodeJS worker mode

@stlite/desktop runs your app on Electron as a desktop app. Electron apps have two processes: the main process which is a Node.js process running in the background, and the renderer process which is a Chromium (browser) process running the app's UI.

By default, stlite executes your Python code on Pyodide running in a Web Worker dispatched by the renderer process, and the renderer process is a browser process so it's sandboxed from the host OS.

When you set the stlite.desktop.nodeJsWorker field in your package.json to true, stlite dispatches the worker as a NodeJS worker that runs in the main process, which is not sandboxed, so you can mount the host OS file system to the virtual file system as described in the previous section.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      "nodeJsWorker": true
    }
  }
}

Limitations

  • Navigation to external resources like st.markdown("[link](https://streamlit.io/)") does not work for security. See https://github.com/whitphx/stlite/pull/445 and let us know if you have use cases where you have to use such external links.
0.54.2

9 days ago

0.53.2

12 days ago

0.53.1

12 days ago

0.54.1

12 days ago

0.54.0

12 days ago

0.52.5

13 days ago

0.53.0

13 days ago

0.52.3

24 days ago

0.52.4

24 days ago

0.52.2

27 days ago

0.52.1

1 month ago

0.52.0

1 month ago

0.51.4

1 month ago

0.51.2

1 month ago

0.51.3

1 month ago

0.51.1

1 month ago

0.51.0

1 month ago

0.49.4

1 month ago

0.50.0

1 month ago

0.49.3

2 months ago

0.49.2

2 months ago

0.49.1

2 months ago

0.48.3

2 months ago

0.48.1

2 months ago

0.49.0

2 months ago

0.48.0

2 months ago

0.47.1

2 months ago

0.47.2

2 months ago

0.46.0

3 months ago

0.46.1

3 months ago

0.47.0

3 months ago

0.45.5

3 months ago

0.45.3

3 months ago

0.45.4

3 months ago

0.45.2

3 months ago

0.45.1

3 months ago

0.44.0

4 months ago

0.45.0

4 months ago

0.42.5

4 months ago

0.43.1

4 months ago

0.42.4

5 months ago

0.41.0

7 months ago

0.38.1

8 months ago

0.38.0

9 months ago

0.36.0

10 months ago

0.42.2

7 months ago

0.42.3

6 months ago

0.42.0

7 months ago

0.42.1

7 months ago

0.40.0

7 months ago

0.39.0

8 months ago

0.37.0

10 months ago

0.35.1

10 months ago

0.35.0

11 months ago

0.34.0

11 months ago

0.33.0

11 months ago

0.32.0

11 months ago

0.29.12

1 year ago

0.29.13

1 year ago

0.29.10

1 year ago

0.29.11

1 year ago

0.29.14

1 year ago

0.29.15

1 year ago

0.29.9

1 year ago

0.30.2

1 year ago

0.30.1

1 year ago

0.30.0

1 year ago

0.29.0

1 year ago

0.29.8

1 year ago

0.29.7

1 year ago

0.29.6

1 year ago

0.29.5

1 year ago

0.29.4

1 year ago

0.29.3

1 year ago

0.29.2

1 year ago

0.29.1

1 year ago

0.31.0

1 year ago

0.28.0

1 year ago

0.27.3

1 year ago

0.27.2

1 year ago

0.27.1

1 year ago

0.27.0

1 year ago

0.26.0

1 year ago

0.25.0

1 year ago

0.24.0

1 year ago

0.23.0

1 year ago

0.21.0

1 year ago

0.20.0

1 year ago

0.19.0

1 year ago

0.18.1

1 year ago

0.19.1

1 year ago

0.18.2

1 year ago

0.17.0

1 year ago

0.18.0

1 year ago

0.22.2

1 year ago

0.21.3

1 year ago

0.22.1

1 year ago

0.21.2

1 year ago

0.22.0

1 year ago

0.21.1

1 year ago

0.16.1

2 years ago

0.16.0

2 years ago

0.15.0

2 years ago

0.14.2

2 years ago

0.14.1

2 years ago

0.14.0

2 years ago

0.13.0

2 years ago

0.12.2

2 years ago

0.12.1

2 years ago

0.12.0

2 years ago

0.11.0

2 years ago

0.10.2

2 years ago