Owen Morris

Building, developing... and growing.

By day I'm the CTO for Doherty Associates, but I love diving into the tech and can't stop programming.

This is my outlet covering the things that interest me technically in Cloud, AI, Data and Dev but are far too in-depth for corporate use!

Occasional references to being husband and Dad, very rarely runner.

Diving (back) into Python - Streamlit

08/01/2025

As part of my ongoing dive back into Python and a parallel exploration into tooling around AI, I've been building a few proof of concept applications and have needed to throw together a quick UI. I spent a little time looking at the options in the space that could save me time versus using something more heavyweight like React and evaluated Streamlit, Plotly Dash and Shiny for Python. Streamlit was the one that I felt was the best fit for what I was doing because most of my applications were text based and didn't have many visualisations, which is where the other two excel.

About Streamlit

Streamlit is a python based framework that in its own words:

Streamlit is an open-source Python framework for data scientists and AI/ML engineers to deliver interactive data apps – in only a few lines of code.

I think it actually lives up to the billing! Technically, the way that it operates is that you define a python script that's run by the main Streamlit web server, and python statements in the script get translated to UI elements. Every time the UI is updated, the script runs. This means that creating an application is very simple. There's built in widgets that do most of the things that you'd expect - inputs, selects through to images, data tables and graphs. It's also well integrated into the Python data ecosystem and has integration with libraries like Pandas.

The good

Firstly, the speed of getting started is really quick and you get immediate feedback on how it's working, with live reloads happening as you modify the script. There's good integration between the product and the Python data ecosystem with strong visuals coming from lots of different visualisation libraries, builtin integration with Pandas dataframes and there's a good ecosystem of plugins. I was fairly quickly able to get a sample LLM app up and running and integrated with one of the agentic AI frameworks.

The session state system is relatively straightforward and caching of results is possible. The fact that the script is re-run for every state change makes this quite essential and does make it more complex, so you lose some of the initial simplicity.

Deployment

Getting the app up and running was fairly straightforward too, I deployed it as an Azure App Service for Containers via Bicep and used github actions to build the Docker container and push it to the registry, and then pull the new version to the app service via the Github Webapps Deploy action - just pass the image name in as the parameter, similar to (this example)[https://github.com/Azure/actions-workflow-samples/blob/master/AppService/docker-webapp-container-on-azure.yml]. I found this to be the best route after having issues getting the deployment working as a Python app service - mostly relating to the time taken to pull the dependencies in the App Service. A basic plan (B1) was sufficient - so the thing was around the same price overall as something like static web apps. App Services requires the server to run on port 8000.

Authentication

Using authentication was then built-in via App Services EasyAuth (and getting the login details is possible via Streamlit, although not formally supported) - see the snippet below:

import streamlit as st
import base64
import json

from streamlit.web.server.websocket_headers import _get_websocket_headers
headers = _get_websocket_headers()
auth = headers.get('X-Ms-Client-Principal')
name = headers.get('X-Ms-Client-Principal-Name')
claimsprincipal = json.loads(base64.b64decode(auth).decode('utf-8'))

The not so good

Styling is one of the main limitations to the toolkit. I wanted to add corporate branding to the frontend, but aside from a built-in theming system that allows you to change colours etc, it's hard to customise the look and feel. I followed a few articles that were on the web to do this, which used the st.markdown() call to inject a stylesheet into the UI, and customise the left navigation bar that way through adding content and overriding the built-in Streamlit styles, but it's not very ergonomic (as the original styling appears briefly before the stylesheet applies) and this is likely to be brittle if the CSS classes that Streamlit use change in the future. Nonetheless, it did the basics of getting corporate branding such as logos into the UI for me relatively quickly.

Other limitations are that multi-user and authorisation is not really supported, so it does limit the usefulness of the tool overall (to me anyway).

Conclusion

So, would I use Streamlit again - yes, probably, but it'd be a quick internal tool that would be used by engineers and not end users. It's probably the fastest way to get to a UI that I've tried so far, but the limitations are frustratingly limiting, so it'll probably stay as part of a niche in my toolbox - and I'll continue looking for alternatives and reaching for React and Svelte in the meantime.