Scriptone Scriptone

Getting Started with Streamlit (Text Output and More)

blog-image

Overview

While I can work with Tauri and web technologies, I felt the desire to create apps easily using just Python. Although Gradio is another option, I’m the type who deliberately uses Tauri and web frameworks, so I became interested in Streamlit, which is less simplified than Gradio but compatible with Python’s diverse libraries. I’ll be building things step by step.

Installation

Python 3.9 to 3.13 is required. As of November 21, 2025, Python 3.14 doesn’t seem to be recommended, so please be aware. Since it’s a Python library, you can install it with pip.

pip install streamlit

If you’re using uv or a virtual environment, after installation, run the streamlit hello command to open a demo in your browser. However, the demo code was a bit overwhelming at first, so I’ll learn how to write Streamlit apps while referring to the Documentation.

Hello World

Let’s write the classic Hello World in Streamlit style. Create projects/hello_world/app.py with the following:

import streamlit as st

st.write("Hello World")

After that, run streamlit run projects/hello_world/app.py and Hello World will be displayed in your browser. If you change st.write to st.title, you can output larger text.

import streamlit as st

# st.write("Hello world")
st.title("Hello world")

Displaying Text Like It’s Being Typed

By combining a generator with st.write_stream, you can display text as if it’s being typed. In addition to strings, it also supports automatic parsing of Pandas DataFrames and Markdown.

import time

import numpy as np
import pandas as pd
import streamlit as st


def stream_data(*itrs, sleep_time: float = 0.025):
    def inner():
        for itr in itrs:
            if isinstance(itr, str):
                for char in itr:
                    yield char
                    time.sleep(sleep_time)
            else:
                yield itr
                time.sleep(sleep_time)

    return inner


text = "Streamlit is convenient because you can develop both the backend and frontend using only Python!"
df = pd.DataFrame(
    np.random.randn(5, 10),
    columns=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
)
additional_text = "You can also display **Pandas DataFrames** in a **tabular format** like the one above."
if st.button("Stream data"):
    st.write_stream(stream_data(text, df, additional_text))

I’ve deployed the app at https://rmc8-streamlit-practice-projectstyperwritter-effectapp-zwmnbe.streamlit.app/ to see it in action. When you press the button, you can see the text being displayed sequentially, like a generative AI response. This is useful for displaying AI responses in real-time via streaming, giving users the impression of real-time answers.

Magic

When you write just variables or values, they are displayed as-is. This is similar to interactive Python processing or Jupyter Lab, where you can output variables without using print, but you can display multiple variables or values at once.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.DataFrame({"col1": [1, 2, 3]})
df

x = 10
"x", x

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

Nothing happens if you run this as plain Python, but through streamlit run app.py, you can confirm that the variable contents are output. You can also disable this magic feature in .streamlit/config.toml.

[runner]
magic = false

There are many text-related operations, so let’s check them one by one.

Markdown

To display formatted Markdown, use st.markdown.

import streamlit as st

st.markdown("*Streamlit* is **really** ***cool***.")
st.markdown('''
    :red[Streamlit] :orange[can] :green[write] :blue[text] :violet[in]
    :gray[pretty] :rainbow[colors] and :blue-background[highlight] text.''')
st.markdown("Here's a bouquet —\
            :tulip::cherry_blossom::rose::hibiscus::sunflower::blossom:")

multi = '''If you end a line with two spaces,
a soft return is used for the next line.

Two (or more) newline characters in a row will result in a hard return.
'''
st.markdown(multi)

The structure is st.markdown(body, unsafe_allow_html=False, *, help=None, width="stretch"), but you’ll mainly use the width parameter. While you can enable HTML by setting unsafe_allow_html to True, it’s better to first consider using st.html and avoid setting this option to True when possible.

Width has three types: stretch to fit the layout, content to set width based on text width, and pixel specification as a number (int). While you can set the width precisely, for a framework meant to be easy to use, stretch or content will be your first choice. This can be used in other text-related operations too, so it’s good to remember.

You can display a header with st.header. Headers correspond to HTML’s h2. The st.title that appeared earlier corresponds to h1. So for subsections within a page, you can use st.header to create headings and anchors for table of contents, and use the divider argument to create underlines for the table of contents.

import streamlit as st

st.header("_Streamlit_ is :blue[cool] :sunglasses:")
st.header("This is a header with a divider", divider="gray")
st.header("These headers have rotating dividers", divider=True)
st.header("One", divider=True)
st.header("Two", divider=True)
st.header("Three", divider=True)
st.header("Four", divider=True)

Subheader

You can display a subheader with st.subheader. This corresponds to h3h6. So the usage is almost the same as header, but since h4h6 are grouped together, it’s not suitable for building large structures within a single page. Conversely, it’s suitable for creating simple pages, with the advantage of being able to create apps quickly and clearly.

Badge

To display text with a background color, use st.badge. There’s also a dedicated syntax for markdown.

import streamlit as st

st.badge("1.0.0", width="content")
st.badge("Success", icon=":material/check:", color="green")
st.markdown(
    ":violet-badge[:material/star: Favorite] Streamlit is :blue[cool] :sunglasses:"
)

Since displaying elements as-is causes line breaks, if you need to display text after a badge, you’ll use markdown.

Caption

Used for figure/table descriptions, supplementary information for UI components, disclaimers, and notes.

import streamlit as st

st.caption("This is a string that explains something above.")
st.caption("A caption with _italics_ :blue[colors] and emojis :sunglasses:")

Code Block

To display a code block, use st.code. Syntax highlighting is also possible by specifying the language.

import streamlit as st

code = """
function hello() {
    console.log("Hello Streamlit!");
}
"""
st.code(
    code,
    language="javascript",
    line_numbers=True,
)

Echo

This isn’t intuitive from the method name alone, but it’s a method that outputs the code within a block when using with st.echo():.

import streamlit as st

with st.echo():
    def hello():
        return "Hello Streamlit!"
    st.write(hello())

The code within the with block is displayed as a code block. If there are operations like st.write inside, the processing is displayed below the code block. It seems useful for code tutorials, demos, debugging information sharing, etc., but compared to other methods, the use cases seem limited.

Text

Use this for pure text output without parsing markdown or html.

import streamlit as st

st.text("This is text\n[and more text](that's not a Markdown link).")

LaTeX

Used to display mathematical formulas using LaTeX.

import streamlit as st

st.latex(r'''
    a + ar + a r^2 + a r^3 + \cdots + a r^{n-1} =
    \sum_{k=0}^{n-1} ar^k =
    a \left(\frac{1-r^{n}}{1-r}\right)
    ''')

Divider

Used to display a divider line within a page.

import streamlit as st

st.divider()

Help

You can easily display help for objects.

import streamlit as st


class Dog:
    """A typical dog."""

    def __init__(self, breed, color):
        self.breed = breed
        self.color = color

    def bark(self):
        return "Woof!"


dog = Dog(breed="Golden Retriever", color="Brown")
st.help(dog)
st.help(dict)

Since you can display the state of objects, methods, etc., it seems useful for education, demos, and debugging.

HTML

You can display HTML with st.html. It’s desirable to display only trusted HTML.

import streamlit as st

st.html(
    "<p><span style='text-decoration: line-through double red;'>Oops</span>!</p>"
)

Impressions of Streamlit So Far

While there are HTML and Markdown parsing features, you can create web applications using only Python, and the ability to write processes concisely in an integrated way with Python, such as displaying DataFrames and help, gives it unique strengths for Python that aren’t found in TypeScript, making it look very convenient. Just with text-related operations alone, there are this many types, so I think you can fully create the apps you want. Also, there are still many features not covered yet, such as displaying tables with Pandas, interactive charts with Polars, map displays, and handling JSON and dict. There are also web form features like page links and checkboxes, so I’ll write another article and continue learning Streamlit.

comment

Loading comments...