Documentation
¶
Overview ¶
Package st is a from-scratch, standard-library-only Go port of Python's Streamlit: a framework for building interactive web and data apps by writing a plain script.
The model ¶
You write an app function with the signature func(s *st.Session). Inside it you call methods on the session to build the page: s.Title, s.Write, s.Slider, s.Button and so on. Each call appends one element to the page's element tree, and each widget call returns the widget's current value. The framework runs your app function top to bottom to produce the page.
The defining behaviour of Streamlit, reproduced faithfully here, is rerun-on-interaction. When the user interacts with any widget, the entire app function runs again from the top. Widget values are restored from per-session state, so a slider you dragged reads its new position on the next run, and any State you stored persists too. The freshly built element tree is diffed against the page and the browser updates. This means app code can be written as a simple straight-line script: there are no callbacks, event handlers, or manual DOM updates.
Two rules follow from that model and are worth internalising early. Session.Stop halts a run and Session.Rerun abandons one and starts it again from the top. And widget state lives exactly as long as the app keeps rendering the widget: state for a widget a run did not draw is discarded at the end of that run, so hiding and revealing a widget starts it from its default — the same behaviour as Streamlit. Give any widget that is not unconditionally rendered an explicit key.
Sessions and containers ¶
A Session represents one browser connection. It embeds the root Container, so all display and widget methods are available directly on the session. Layout helpers such as Container.Columns and Container.Expander return further containers that render nested regions; Session.Sidebar returns the sidebar container. Because every method lives on *Container, the same API works uniformly for the main body, the sidebar and each column.
Transport and frontend ¶
Run starts an HTTP server. It serves a small, dependency-free single-page frontend (embedded via go:embed) that renders the JSON element tree and posts widget-change events back to POST /api/run. The server applies the event, reruns the app function for that session, and returns the new tree. The whole protocol is plain JSON request/response — no third-party modules, no JavaScript frameworks, no external charting library (charts are rendered to inline SVG on the server).
Example ¶
package main
import "github.com/malcolmston/streamlit/st"
func main() {
st.Run(app, ":8501")
}
func app(s *st.Session) {
s.Title("Hello, Streamlit-Go")
n := s.Slider("Points", 0, 100, 50, 1)
s.LineChart(series(int(n)))
if s.Button("Celebrate") {
s.Success("🎉")
}
}
Widgets, layout, media and charts ¶
Beyond the basics the package offers a broad surface, each piece backed by per-session state and rendered by the embedded frontend:
- Display and data: Container.Title, Container.Header, Container.Subheader, Container.Markdown, Container.Write, Container.Metric, Container.Code, Container.JSON, Container.Table and Container.DataFrame. Tabular structs and slices render automatically, and alerts (Container.Success, Container.Info, Container.Warning, Container.Error) draw the callout boxes.
- Widgets: Container.Button, Container.Checkbox, Container.Toggle, Container.Slider, Container.SelectSlider, Container.NumberInput, Container.TextInput, Container.TextArea, Container.SelectBox, Container.Radio, Container.MultiSelect, Container.DateInput, Container.TimeInput, Container.ColorPicker, Container.Feedback, Container.DownloadButton and Container.FileUploader. The extended set adds Container.Pills, Container.SegmentedControl, Container.PrimaryButton, Container.PasswordInput, Container.TextInputMax, Container.NumberInputRange, Container.SliderRange, Container.SelectSliderRange, Container.DateRangeInput, Container.CameraInput and Container.AudioInput.
- Layout: Container.Columns, Container.ColumnsWeighted, Container.Container, Container.BorderedContainer, Container.Expander, Container.Tabs, Container.Popover, Container.Status, Container.Empty and Session.Sidebar.
- Forms: Container.Form with Container.FormSubmitButton batch widget updates until the form is submitted.
- Chat: Container.ChatMessage and Container.ChatInput.
- Media: Container.Image, Container.Logo, Container.Audio, Container.Video and Container.Map. Bytes and image.Image values are embedded as base64 data URIs.
- Charts (server-side SVG): Container.LineChart, Container.AreaChart, Container.BarChart, Container.ScatterChart, Container.PieChart and Container.Histogram.
- Caching: Session.Cache memoises an expensive computation process-wide, across reruns and sessions, with an optional TTL — the analogue of st.cache_data. Session.CacheResource is the st.cache_resource analogue: a singleton that never expires. CacheClear, CacheDelete and CacheResourceClear invalidate them.
Safety ¶
Text rendered as Markdown is escaped before any formatting is applied, and a link or media URL is emitted only if its scheme is on an allowlist, so a javascript: target cannot reach an href. Raw HTML is opt-in through Container.Html and Container.MarkdownUnsafe. Both POST endpoints reject a request whose Origin header names another site, and every allocation a remote caller can grow — sessions, uploaded bytes, request bodies, cache entries, widget keys — is bounded; see Options.
Deferred features ¶
This is a compact reimplementation of a large framework. Deliberately deferred: custom components, multipage apps, fragments, real-time streaming/async widgets, in-place dataframe editing, query parameters and theming APIs. The synchronous long-poll-free transport also means Container.Spinner and Container.Progress are snapshots of the completed run rather than live-updating during work. The full list, and every place this port's semantics differ from upstream on purpose, is in API-DEVIATIONS.md.
Index ¶
- Constants
- func CacheClear()
- func CacheDelete(key string) bool
- func CacheLen() int
- func CacheResourceClear()
- func CacheSetMaxEntries(n int)
- func Handler(app func(*Session)) http.Handler
- func HandlerWithOptions(app func(*Session), opts Options) http.Handler
- func Run(app func(*Session), addr string) error
- func RunWithOptions(app func(*Session), addr string, opts Options) error
- type Container
- func (c *Container) AreaChart(series ...[]float64)
- func (c *Container) Audio(src any)
- func (c *Container) AudioInput(label string, key ...string) []UploadedFile
- func (c *Container) Badge(label string, color ...string)
- func (c *Container) Balloons()
- func (c *Container) BarChart(series ...[]float64)
- func (c *Container) BorderedContainer() *Container
- func (c *Container) Button(label string, key ...string) bool
- func (c *Container) CameraInput(label string, key ...string) []UploadedFile
- func (c *Container) Caption(text string)
- func (c *Container) ChatInput(placeholder string, key ...string) string
- func (c *Container) ChatMessage(role string) *Container
- func (c *Container) Checkbox(label string, def bool, key ...string) bool
- func (c *Container) Code(code, lang string)
- func (c *Container) ColorPicker(label, def string, key ...string) string
- func (c *Container) Columns(n int) []*Container
- func (c *Container) ColumnsWeighted(weights []float64) []*Container
- func (c *Container) Container() *Container
- func (c *Container) DataFrame(data any, caption ...string)
- func (c *Container) DateInput(label, def string, key ...string) string
- func (c *Container) DateRangeInput(label, defStart, defEnd string, key ...string) (string, string)
- func (c *Container) Divider()
- func (c *Container) DownloadButton(label, filename string, data []byte, key ...string) bool
- func (c *Container) Echo(code string)
- func (c *Container) Empty() *Container
- func (c *Container) Error(text string)
- func (c *Container) Exception(err error)
- func (c *Container) Expander(label string, expanded bool) *Container
- func (c *Container) Feedback(kind string, key ...string) int
- func (c *Container) FileUploader(label string, key ...string) []UploadedFile
- func (c *Container) Form(key string) *Container
- func (c *Container) FormSubmitButton(label string) bool
- func (c *Container) Header(text string)
- func (c *Container) Help(value any)
- func (c *Container) Histogram(data []float64, bins int)
- func (c *Container) Html(html string)
- func (c *Container) Image(src any, caption ...string)
- func (c *Container) Info(text string)
- func (c *Container) JSON(value any, collapsed ...bool)
- func (c *Container) Latex(expr string)
- func (c *Container) LineChart(series ...[]float64)
- func (c *Container) LinkButton(label, url string)
- func (c *Container) Logo(src any)
- func (c *Container) Map(points []MapPoint)
- func (c *Container) Markdown(text string)
- func (c *Container) MarkdownUnsafe(text string)
- func (c *Container) Metric(label, value, delta string)
- func (c *Container) MetricColored(label, value, delta, deltaColor string)
- func (c *Container) MultiSelect(label string, options []string, key ...string) []string
- func (c *Container) NumberInput(label string, def float64, key ...string) float64
- func (c *Container) NumberInputRange(label string, min, max, def float64, key ...string) float64
- func (c *Container) PageLink(url, label string)
- func (c *Container) PasswordInput(label, def string, key ...string) string
- func (c *Container) PieChart(values []float64, labels []string)
- func (c *Container) Pills(label string, options []string, key ...string) []string
- func (c *Container) Popover(label string) *Container
- func (c *Container) PrimaryButton(label string, key ...string) bool
- func (c *Container) Progress(value float64)
- func (c *Container) Radio(label string, options []string, key ...string) string
- func (c *Container) ScatterChart(xs, ys []float64)
- func (c *Container) SegmentedControl(label string, options []string, key ...string) string
- func (c *Container) SelectBox(label string, options []string, key ...string) string
- func (c *Container) SelectSlider(label string, options []string, key ...string) string
- func (c *Container) SelectSliderRange(label string, options []string, key ...string) (string, string)
- func (c *Container) Slider(label string, min, max, def, step float64, key ...string) float64
- func (c *Container) SliderRange(label string, min, max, low, high, step float64, key ...string) (float64, float64)
- func (c *Container) Snow()
- func (c *Container) Spinner(label string)
- func (c *Container) Status(label string, state ...string) *Container
- func (c *Container) Subheader(text string)
- func (c *Container) Success(text string)
- func (c *Container) Table(data any, caption ...string)
- func (c *Container) Tabs(labels []string) []*Container
- func (c *Container) Text(text string)
- func (c *Container) TextArea(label, def string, key ...string) string
- func (c *Container) TextInput(label, def string, key ...string) string
- func (c *Container) TextInputMax(label, def string, maxChars int, key ...string) string
- func (c *Container) TimeInput(label, def string, key ...string) string
- func (c *Container) Title(text string)
- func (c *Container) Toast(message string, icon ...string)
- func (c *Container) Toggle(label string, def bool, key ...string) bool
- func (c *Container) Video(src any)
- func (c *Container) Warning(text string)
- func (c *Container) Write(args ...any)
- type Element
- type MapPoint
- type Options
- type Session
- func (s *Session) Cache(key string, compute func() any, ttl ...time.Duration) any
- func (s *Session) CacheResource(key string, create func() any) any
- func (s *Session) ID() string
- func (s *Session) Rerun()
- func (s *Session) SetPageConfig(title, icon string)
- func (s *Session) Sidebar() *Container
- func (s *Session) Stop()
- type State
- func (s *State) Clear()
- func (s *State) Delete(key string)
- func (s *State) Get(key string) (any, bool)
- func (s *State) GetBool(key string, def bool) bool
- func (s *State) GetFloat(key string, def float64) float64
- func (s *State) GetInt(key string, def int) int
- func (s *State) GetString(key, def string) string
- func (s *State) Has(key string) bool
- func (s *State) Keys() []string
- func (s *State) Len() int
- func (s *State) Set(key string, value any)
- func (s *State) SetDefault(key string, value any) bool
- type UploadedFile
Examples ¶
Constants ¶
const ( // DefaultMaxSessions is the largest number of concurrent sessions kept in // memory. When the limit is reached the least recently used session is // evicted. DefaultMaxSessions = 1000 // DefaultSessionIdleTimeout is how long a session survives without a // request before it is dropped. DefaultSessionIdleTimeout = 30 * time.Minute // DefaultMaxUploadBytes is the largest accepted body for a single // multipart upload request, across all of its file parts. DefaultMaxUploadBytes int64 = 32 << 20 // 32 MiB // DefaultMaxRequestBytes is the largest accepted body for POST /api/run. DefaultMaxRequestBytes int64 = 1 << 20 // 1 MiB // DefaultMaxWidgetEntries is the largest number of widget-state entries a // single session may retain. DefaultMaxWidgetEntries = 1024 // DefaultMaxWidgetStateBytes is the largest total size of the values held // in one session's widget state. DefaultMaxWidgetStateBytes int64 = 1 << 20 // 1 MiB )
Defaults applied by Handler and Run. Every one of them exists because the value it bounds is ultimately chosen by a remote client: without a ceiling a single caller could pin unbounded memory (sessions, uploaded bytes) on the server. Use Options with HandlerWithOptions to tune them.
const DefaultMaxCacheEntries = 1024
DefaultMaxCacheEntries bounds the process-wide table used by Session.Cache. Streamlit's @st.cache_data defaults to max_entries=None (unbounded); this port bounds it because a cache whose keys are derived from user input otherwise grows until the process dies. Change it with CacheSetMaxEntries.
Variables ¶
This section is empty.
Functions ¶
func CacheClear ¶ added in v0.2.0
func CacheClear()
CacheClear removes all entries from the process-wide cache used by Session.Cache. It is primarily useful in tests and for manual invalidation. Resources registered with Session.CacheResource survive; clear those with CacheResourceClear.
func CacheDelete ¶ added in v0.4.0
CacheDelete removes a single entry from the data cache used by Session.Cache, forcing the next call for that key to recompute. It reports whether an entry was present. It is the targeted counterpart to CacheClear, matching the per-function .clear() Streamlit exposes on a cached function.
func CacheLen ¶ added in v0.4.0
func CacheLen() int
CacheLen reports how many entries the data cache currently holds. Resources registered with Session.CacheResource are not counted.
func CacheResourceClear ¶ added in v0.4.0
func CacheResourceClear()
CacheResourceClear discards every singleton registered with Session.CacheResource, so the next call for each key builds a fresh one. It mirrors st.cache_resource.clear() and is chiefly useful in tests.
func CacheSetMaxEntries ¶ added in v0.4.0
func CacheSetMaxEntries(n int)
CacheSetMaxEntries sets how many entries Session.Cache retains. When the table is full the entry inserted longest ago is evicted. A value of zero or less restores DefaultMaxCacheEntries. It affects Session.Cache only; Session.CacheResource entries are never evicted.
func Handler ¶
Handler returns the http.Handler that serves the app with the default Options. It is exposed so the app can be mounted inside a larger server or driven in tests; most callers should use Run instead.
func HandlerWithOptions ¶ added in v0.4.0
HandlerWithOptions is Handler with explicit resource limits and origin policy. See Options.
Types ¶
type Container ¶
type Container struct {
// contains filtered or unexported fields
}
Container is a region of the page into which elements are appended. The root container is embedded in Session so its methods are reachable directly on the session; layout helpers such as Container.Columns and Container.Expander return additional containers that render nested regions.
Every display and widget method lives on *Container, which is what lets the same API be used for the main body, the sidebar, and individual columns.
Example (ColumnsWeighted) ¶
ExampleContainer_columnsWeighted lays out a wide chart beside a narrow summary, mirroring st.columns([3, 1]).
app := func(s *Session) {
cols := s.ColumnsWeighted([]float64{3, 1})
cols[0].LineChart([]float64{1, 4, 9})
cols[1].Metric("Peak", "9", "+5")
}
s := newSession()
row := s.run(app).Children[1].Children[0]
for _, col := range row.Children {
fmt.Printf("%v -> %s\n", col.Props["weight"], col.Children[0].Type)
}
Output: 3 -> chart 1 -> metric
Example (MarkdownUnsafe) ¶
ExampleContainer_markdownUnsafe contrasts the safe default with the opt-in. Markdown ships the text for escaping in the browser; MarkdownUnsafe flags it to be passed through as HTML, which is why it must never carry untrusted input.
app := func(s *Session) {
s.Markdown(`<b>from a user</b>`)
s.MarkdownUnsafe(`<b>from me</b>`)
}
s := newSession()
for _, el := range s.run(app).Children[1].Children {
fmt.Println(el.Props["text"], "unsafe:", el.Props["unsafeAllowHTML"])
}
Output: <b>from a user</b> unsafe: <nil> <b>from me</b> unsafe: true
func (*Container) AreaChart ¶
AreaChart adds a filled area chart. See Container.LineChart for the series convention.
func (*Container) Audio ¶ added in v0.2.0
Audio adds an audio player. src may be a URL string or raw audio bytes (for example WAV or MP3), which are embedded as a data URI.
func (*Container) AudioInput ¶ added in v0.3.0
func (c *Container) AudioInput(label string, key ...string) []UploadedFile
AudioInput adds a control that records audio from the user's microphone and returns the recorded files for the current session, mirroring Streamlit's st.audio_input. It works like Container.CameraInput, receiving bytes over the multipart /api/upload endpoint keyed by the widget key.
func (*Container) Badge ¶ added in v0.3.0
Badge adds a small coloured pill label, mirroring Streamlit's st.badge. color is an optional colour name (for example "blue", "green", "red", "orange", "violet" or "grey"); an empty or unrecognised colour defaults to "blue".
func (*Container) Balloons ¶ added in v0.3.0
func (c *Container) Balloons()
Balloons triggers the celebratory balloons animation, mirroring Streamlit's st.balloons. It adds a one-shot effect element to the page.
func (*Container) BarChart ¶
BarChart adds a bar chart. See Container.LineChart for the series convention. Multiple series are drawn as grouped bars.
func (*Container) BorderedContainer ¶ added in v0.3.0
BorderedContainer adds a nested grouping region drawn with a visible border and returns a container for it, mirroring Streamlit's st.container(border= True). It behaves like Container.Container but is visually delimited, which is useful for grouping related output into a card.
func (*Container) Button ¶
Button adds a clickable button and returns true on the single run triggered by a click. An optional stable key may be supplied as the final argument.
func (*Container) CameraInput ¶ added in v0.3.0
func (c *Container) CameraInput(label string, key ...string) []UploadedFile
CameraInput adds a control that captures a photo from the user's webcam and returns the captured image files for the current session, mirroring Streamlit's st.camera_input. Like Container.FileUploader the bytes arrive over the multipart /api/upload endpoint keyed by the widget key and are held in session state; the returned slice is empty until a photo is taken.
func (*Container) ChatInput ¶ added in v0.2.0
ChatInput adds a chat entry box pinned to the bottom of its region and returns the message the user last submitted, or the empty string before any submission. Submitting a message (pressing Enter) reruns the app with the new value available. An optional stable key may be supplied.
if msg := s.ChatInput("Ask me anything"); msg != "" {
s.ChatMessage("user").Text(msg)
}
func (*Container) ChatMessage ¶ added in v0.2.0
ChatMessage adds a chat message bubble attributed to role (commonly "user" or "assistant") and returns a container for the message body. Any elements may be placed inside it, so a message can contain markdown, tables, charts, and so on.
m := s.ChatMessage("assistant")
m.Markdown("Here is your **answer**.")
func (*Container) Checkbox ¶
Checkbox adds a checkbox initialised to def and returns its current state.
func (*Container) Code ¶
Code adds a syntax-highlight-styled code block. lang is an advisory language label (for example "go" or "python") and may be empty.
func (*Container) ColorPicker ¶ added in v0.2.0
ColorPicker adds a colour selector and returns the chosen colour as a "#rrggbb" hex string. def is the initial value; an empty def defaults to black ("#000000").
func (*Container) Columns ¶
Columns splits the current region into n side-by-side columns and returns a container for each. Elements added to a returned container render within that column. If n is less than one it is treated as one.
c1, c2 := s.Columns(2)[0], s.Columns(2)[1] // (illustrative)
cols := s.Columns(2)
cols[0].Metric("Left", "1", "")
cols[1].Metric("Right", "2", "")
func (*Container) ColumnsWeighted ¶ added in v0.4.0
ColumnsWeighted splits the current region into columns whose widths are proportional to weights, mirroring Streamlit's st.columns([2, 1]) — which takes a list of relative widths rather than a count.
Non-positive and non-finite weights are treated as 1 so a stray zero cannot collapse a column to nothing. An empty weights slice yields a single full-width column.
cols := s.ColumnsWeighted([]float64{3, 1})
cols[0].LineChart(series) // three quarters of the width
cols[1].Metric("Peak", "42", "")
func (*Container) Container ¶
Container adds a nested, undecorated grouping region and returns a container for it. It is useful for grouping elements or for building output out of order.
func (*Container) DataFrame ¶
DataFrame renders tabular data like Container.Table but adds a client-side sorting hint, so column headers can be clicked to sort the rows in the browser. It mirrors Streamlit's st.dataframe entry point and accepts an optional caption.
func (*Container) DateInput ¶ added in v0.2.0
DateInput adds a calendar date field and returns the selected date as an ISO-8601 string ("2006-01-02"). def is the initial value and may be empty.
func (*Container) DateRangeInput ¶ added in v0.3.0
DateRangeInput adds a calendar control that selects a start and end date and returns them as ISO-8601 strings ("2006-01-02"), mirroring Streamlit's st.date_input used with a tuple default. defStart and defEnd are the initial values and may be empty. The earlier date is always returned first.
func (*Container) DownloadButton ¶ added in v0.2.0
DownloadButton adds a button that downloads data as a file named filename when clicked, and returns true on the single run triggered by the click. The bytes are embedded in the page as a base64 data URI, so this is best suited to modestly sized payloads. The content type is detected from the data.
func (*Container) Echo ¶ added in v0.3.0
Echo adds a read-only display of Go source code, mirroring Streamlit's st.echo (which shows the code inside its block). The code is rendered as a syntax-styled block tagged as Go.
func (*Container) Empty ¶ added in v0.2.0
Empty adds a single placeholder region and returns a container for it. Because the element tree is rebuilt on every run, an Empty is most useful as a stable slot whose contents are decided later in the same run.
func (*Container) Exception ¶ added in v0.3.0
Exception adds a formatted error box for err, mirroring Streamlit's st.exception. The error's message and its Go type name are shown. A nil error renders an empty exception box.
func (*Container) Expander ¶
Expander adds a collapsible section with the given label and returns a container for its body. When expanded is true the section starts open.
func (*Container) Feedback ¶ added in v0.2.0
Feedback adds a rating control and returns the selected score, or -1 when nothing has been chosen yet. kind selects the style: "stars" yields a 0–4 five-star rating and "thumbs" yields a 0 (down) / 1 (up) control. Any other value is treated as "stars".
func (*Container) FileUploader ¶ added in v0.2.0
func (c *Container) FileUploader(label string, key ...string) []UploadedFile
FileUploader adds a file selection control and returns the files uploaded for it in the current session. Bytes are received over a multipart POST to /api/upload and held in session state (they are not part of the JSON element tree); only filenames are echoed to the browser. The returned slice is empty until the user uploads at least one file.
func (*Container) Form ¶ added in v0.2.0
Form adds a form region identified by key and returns a container for its body. Widgets appended to the returned container defer their state updates: interacting with them does not rerun the app. Instead the browser stages their values locally and commits them all at once when a Container.FormSubmitButton inside the form is clicked, at which point the app reruns with every staged value applied together.
This batching is the point of a form: several inputs can be changed and then submitted as a unit, avoiding a rerun per keystroke.
f := s.Form("signup")
name := f.TextInput("Name", "")
age := f.NumberInput("Age", 18)
if f.FormSubmitButton("Register") {
s.Success("Welcome, " + name)
_ = age
}
func (*Container) FormSubmitButton ¶ added in v0.2.0
FormSubmitButton adds the submit button for the enclosing form and returns true on the single run triggered by its click. It must be called on a container returned by Container.Form; used elsewhere it behaves like a disconnected button that never batches values.
func (*Container) Help ¶ added in v0.3.0
Help adds an introspective description of value, mirroring Streamlit's st.help. The value's Go type and its formatted representation are shown, which is handy for quickly inspecting a variable while building an app.
func (*Container) Histogram ¶ added in v0.2.0
Histogram adds a histogram of data grouped into the given number of bins (clamped to at least one), rendered as a bar chart. It is a convenience over bucketing the data yourself and calling Container.BarChart.
func (*Container) Html ¶ added in v0.3.0
Html adds a block of raw, unescaped HTML, mirroring Streamlit's st.html. The markup is inserted verbatim, so only pass HTML you trust — untrusted input can inject script into the page.
func (*Container) Image ¶ added in v0.2.0
Image adds an image. src may be a URL string, PNG/JPEG (or other) bytes, or an image.Image value, which is encoded to PNG. An optional caption is shown beneath the image.
func (*Container) JSON ¶
JSON adds a pretty-printed JSON view of value. Values that cannot be marshalled are rendered using their Go default formatting instead. When the optional collapsed argument is true the view starts collapsed behind a disclosure toggle in the browser.
func (*Container) Latex ¶ added in v0.3.0
Latex adds a block of mathematics written in LaTeX. expr is the raw LaTeX source without surrounding delimiters, for example `\int_a^b f(x)\,dx`. It mirrors Streamlit's st.latex; the embedded frontend renders the expression in a dedicated math block.
func (*Container) LineChart ¶
LineChart adds a line chart. Each argument is one numeric series; series are plotted against a shared 0..N-1 x-axis and rendered to inline SVG on the server using only the standard library.
func (*Container) LinkButton ¶ added in v0.3.0
LinkButton adds a button that navigates to url when clicked, mirroring Streamlit's st.link_button. Unlike Container.Button it does not rerun the app; it is a styled hyperlink.
func (*Container) Logo ¶ added in v0.2.0
Logo adds a small brand image, typically shown at the top of the app or sidebar. src accepts the same values as Container.Image.
func (*Container) Map ¶ added in v0.2.0
Map adds a simple point map. Each point is projected with an equirectangular projection and drawn as a dot over a framed world extent, rendered to inline SVG on the server using only the standard library.
func (*Container) Markdown ¶
Markdown adds text rendered with a small, safe subset of Markdown (ATX headings, bold, italics, inline code, links and unordered lists) by the frontend.
The text is treated as untrusted: every character is HTML-escaped before any formatting is applied, and a link target is emitted only when its scheme is one of http, https, mailto, tel, ftp, ftps or sms — a `javascript:` URL is replaced with "#". This mirrors Streamlit, where st.markdown escapes HTML unless unsafe_allow_html is set; see Container.MarkdownUnsafe for the opt-in.
func (*Container) MarkdownUnsafe ¶ added in v0.4.0
MarkdownUnsafe is Container.Markdown with HTML passed through instead of escaped, mirroring st.markdown(body, unsafe_allow_html=True).
The name is a warning, not decoration: anything in text that looks like a tag becomes a tag, so a string containing untrusted input can inject script into every viewer's page. Use Container.Markdown unless the whole string is under your control. Markdown link targets are still restricted to safe schemes, but raw <a href="javascript:…"> in the HTML is not — that is the point of the opt-in.
func (*Container) Metric ¶
Metric adds a big-number metric with an optional delta indicator. A delta beginning with '-' renders as a negative (downward) change; the coloring can be flipped or disabled with Container.MetricColored.
Alongside the raw delta text, the resolved arrow direction ("up", "down" or "none") and delta colour ("green", "red" or "grey") are attached to the element, matching how Streamlit's st.metric derives them; see Container.MetricColored for the exact rules.
func (*Container) MetricColored ¶ added in v0.2.0
MetricColored is like Container.Metric but controls how the delta is coloured. deltaColor is one of "normal" (positive green, negative red), "inverse" (the reverse, useful when lower is better), or "off" (grey).
The element records the resolved "color" ("green", "red" or "grey") and "direction" ("up", "down" or "none") in addition to the raw delta text and deltaColor mode, mirroring Streamlit's st.metric. See [metricDeltaSignal] for how the sign of the delta text is interpreted.
func (*Container) MultiSelect ¶
MultiSelect adds a multiple-selection control and returns the currently selected options. Selections not present in options are dropped.
func (*Container) NumberInput ¶
NumberInput adds a numeric entry field initialised to def and returns its current value.
func (*Container) NumberInputRange ¶ added in v0.3.0
NumberInputRange adds a numeric entry field bounded to the inclusive range [min, max] and returns its current value clamped to that range, mirroring Streamlit's st.number_input(min_value=…, max_value=…). def is the initial value and is itself clamped.
func (*Container) PageLink ¶ added in v0.3.0
PageLink adds a navigational link to url shown with the given label, mirroring Streamlit's st.page_link. It is rendered as a prominent link rather than a button.
func (*Container) PasswordInput ¶ added in v0.3.0
PasswordInput adds a single-line text field whose contents are masked in the browser and returns its current value, mirroring Streamlit's st.text_input(type="password"). def is the initial value.
func (*Container) PieChart ¶ added in v0.2.0
PieChart adds a pie chart. values gives each slice's magnitude and the optional labels name the slices in order. Non-positive totals render an empty chart.
func (*Container) Pills ¶ added in v0.3.0
Pills adds a row of selectable "pill" chips allowing multiple selections and returns the currently selected options, mirroring Streamlit's st.pills. Selections not present in options are dropped. An optional stable key may be supplied as the final argument.
func (*Container) Popover ¶ added in v0.2.0
Popover adds a button that reveals a small floating panel when clicked and returns a container for the panel's body. The panel is toggled in the browser without rerunning the app, making it a convenient home for extra controls or help text.
func (*Container) PrimaryButton ¶ added in v0.3.0
PrimaryButton adds an emphasised call-to-action button and returns true on the single run triggered by a click, mirroring Streamlit's st.button(type= "primary"). It behaves exactly like Container.Button but is styled as the page's primary action.
func (*Container) Progress ¶
Progress adds a progress bar. value is a fraction in the range [0, 1] and is clamped to that range. Alongside the clamped fraction the element records an integer "percent" in [0, 100] computed as int(value*100), matching the 0–100 completion value Streamlit's st.progress reports.
func (*Container) Radio ¶
Radio adds a group of mutually exclusive radio options and returns the selected option. Behaves like Container.SelectBox for defaults.
func (*Container) ScatterChart ¶ added in v0.2.0
ScatterChart adds a scatter plot of the paired xs and ys values, rendered to inline SVG on the server. Points beyond the shorter of the two slices are ignored. Unlike the line/bar/area charts, the axes are scaled to the data rather than anchored at zero.
func (*Container) SegmentedControl ¶ added in v0.3.0
SegmentedControl adds a single-choice segmented button group and returns the selected option, mirroring Streamlit's st.segmented_control. The first option is selected by default; if options is empty the empty string is returned.
func (*Container) SelectBox ¶
SelectBox adds a drop-down of options and returns the selected option. The first option is selected by default; if options is empty the empty string is returned.
func (*Container) SelectSlider ¶ added in v0.2.0
SelectSlider adds a slider that moves across a set of discrete options and returns the currently selected option. The first option is selected by default. If options is empty the empty string is returned.
func (*Container) SelectSliderRange ¶ added in v0.3.0
func (c *Container) SelectSliderRange(label string, options []string, key ...string) (string, string)
SelectSliderRange adds a slider that selects a contiguous range across a set of discrete options and returns the currently selected low and high options, mirroring Streamlit's st.select_slider used with a tuple default. By default the full range (first to last option) is selected. The returned pair is ordered by position in options. If options is empty two empty strings are returned.
func (*Container) Slider ¶
Slider adds a numeric slider bounded by min and max, initialised to def, and returns its current value. step controls the increment; if step is zero a sensible default of (max-min)/100 is used.
If min and max are supplied out of order they are swapped. When the current value falls outside [min, max] the bounds are widened to include it rather than the value being clamped, matching Streamlit's st.slider — which adjusts the range to fit an out-of-range default instead of moving the value. As a result the returned value is always exactly the resolved value, and min/max on the element may differ from the arguments.
func (*Container) SliderRange ¶ added in v0.3.0
func (c *Container) SliderRange(label string, min, max, low, high, step float64, key ...string) (float64, float64)
SliderRange adds a two-handle range slider bounded by min and max and returns the currently selected low and high values, mirroring Streamlit's st.slider used with a tuple default. low and high are the initial handle positions; both returned values are clamped to [min, max] and the lower is always returned first. step controls the increment; a non-positive step defaults to (max-min)/100.
func (*Container) Snow ¶ added in v0.3.0
func (c *Container) Snow()
Snow triggers the falling-snow animation, mirroring Streamlit's st.snow. It adds a one-shot effect element to the page.
func (*Container) Spinner ¶
Spinner adds a spinner with a label. In this synchronous MVP the spinner is primarily decorative: the element tree is delivered only after the run completes, so a spinner marks a region that performed work rather than animating during it.
func (*Container) Status ¶ added in v0.2.0
Status adds a collapsible status box with a label and a visual state and returns a container for its body. The optional state is one of "running" (default), "complete", or "error"; it selects the icon shown beside the label. Because the app reruns top to bottom, updating a status is simply a matter of calling Status again with a new state on the next run.
st := s.Status("Crunching numbers…", "running")
st.Write("step 1 done")
func (*Container) Table ¶
Table renders tabular data. It accepts:
- [][]string, where the first row is treated as the header;
- a slice of structs, where exported field names become the header and each element becomes a row;
- a single struct, rendered as a one-row table.
An optional caption is shown beneath the table. Anything unsupported falls back to a JSON view.
func (*Container) Tabs ¶ added in v0.2.0
Tabs adds a tabbed region with one tab per label and returns a container for each tab's body, in the same order as labels. Switching between tabs happens entirely in the browser and does not rerun the app. If labels is empty a single unnamed tab is created.
tabs := s.Tabs([]string{"Chart", "Data"})
tabs[0].LineChart(series)
tabs[1].DataFrame(rows)
func (*Container) TextArea ¶
TextArea adds a multi-line text field initialised to def and returns its current value.
func (*Container) TextInput ¶
TextInput adds a single-line text field initialised to def and returns its current value.
func (*Container) TextInputMax ¶ added in v0.3.0
TextInputMax adds a single-line text field that accepts at most maxChars characters and returns its current value, truncated to maxChars runes, mirroring Streamlit's st.text_input(max_chars=…). A maxChars of zero or less imposes no limit.
func (*Container) TimeInput ¶ added in v0.2.0
TimeInput adds a time-of-day field and returns the selected time as a 24-hour "15:04" string. def is the initial value and may be empty.
func (*Container) Toast ¶ added in v0.3.0
Toast adds a transient notification message, mirroring Streamlit's st.toast. An optional leading icon (typically an emoji) may be supplied as the second argument.
func (*Container) Toggle ¶ added in v0.2.0
Toggle adds an on/off switch initialised to def and returns its current state. It behaves like Container.Checkbox but renders as a sliding toggle.
func (*Container) Video ¶ added in v0.2.0
Video adds a video player. src may be a URL string or raw video bytes (for example MP4), which are embedded as a data URI.
func (*Container) Write ¶
Write is the Swiss-army display method, mirroring Streamlit's st.write. It inspects each argument's dynamic type and dispatches to the most appropriate specialised renderer:
- string -> Container.Markdown
- error -> Container.Error
- fmt.Stringer -> Container.Text (via String)
- struct / slice of structs / [][]string -> Container.Table
- map / other slice -> Container.JSON
- everything else -> Container.Text (via fmt.Sprint)
Passing multiple arguments renders each in turn.
type Element ¶
type Element struct {
// Type identifies how the frontend should render the node, for example
// "title", "slider" or "columns".
Type string `json:"type"`
// Key is the stable widget identity. It is empty for non-widget
// elements. Widget interaction events reference this value.
Key string `json:"key,omitempty"`
// Props holds the element's rendered attributes (labels, values, SVG
// markup, table rows, and so on).
Props map[string]any `json:"props,omitempty"`
// Children holds nested elements for layout containers.
Children []*Element `json:"children,omitempty"`
}
Element is a single node in the page's element tree.
The element tree is the serializable description of everything the app wants the browser to display for the current run. Each call such as Container.Title or Container.Slider appends one Element to the tree. Elements are marshalled to JSON and shipped to the embedded frontend, which renders them and, for widgets, sends interaction events back to the server.
An Element carries a Type (interpreted by the frontend renderer), an arbitrary Props bag, an optional Key (stable identity used for widgets), and nested Children (used by layout containers such as columns and expanders).
type MapPoint ¶ added in v0.2.0
MapPoint is a single latitude/longitude coordinate plotted by Container.Map. Latitude is in the range [-90, 90] and longitude in [-180, 180].
type Options ¶ added in v0.4.0
type Options struct {
// MaxSessions caps concurrently retained sessions; <= 0 selects
// [DefaultMaxSessions].
MaxSessions int
// SessionIdleTimeout is how long an idle session is retained; <= 0
// selects [DefaultSessionIdleTimeout].
SessionIdleTimeout time.Duration
// MaxUploadBytes caps a single upload request body; <= 0 selects
// [DefaultMaxUploadBytes].
MaxUploadBytes int64
// MaxRequestBytes caps a single /api/run request body; <= 0 selects
// [DefaultMaxRequestBytes].
MaxRequestBytes int64
// MaxWidgetEntries caps how many widget-state entries one session
// retains; <= 0 selects [DefaultMaxWidgetEntries].
MaxWidgetEntries int
// MaxWidgetStateBytes caps the total size of one session's widget-state
// values; <= 0 selects [DefaultMaxWidgetStateBytes].
MaxWidgetStateBytes int64
// AllowedOrigins lists extra browser origins ("https://app.example.com")
// permitted to drive the app. Same-origin requests are always allowed;
// requests carrying any other Origin are rejected with 403. Leave it nil
// unless the app is deliberately embedded in another site.
AllowedOrigins []string
// AllowAllOrigins disables origin checking entirely. Only set it when the
// app is deliberately public and stateless — with it on, any web page a
// user visits can drive their session (cross-site request forgery).
AllowAllOrigins bool
}
Options configures the HTTP surface returned by HandlerWithOptions. The zero Options is valid and selects the documented default for every field.
type Session ¶
type Session struct {
// State is the persistent per-session key/value store.
State *State
// contains filtered or unexported fields
}
Session represents a single browser connection to the app. It embeds the root Container, so every display and widget method may be called directly on the session (for example s.Title or s.Slider). A fresh Session is created for each new browser and reused for every rerun triggered by that browser.
The app function receives a *Session and builds the page by calling methods on it. On each run the element tree is rebuilt from scratch while widget values and State persist, faithfully reproducing Streamlit's rerun-on-interaction model.
Example ¶
ExampleSession demonstrates building a page and inspecting the resulting element tree without an HTTP server. Rendering an app function against a session produces a deterministic tree that can be walked and asserted on.
app := func(s *Session) {
s.Title("Report")
n := s.Slider("Count", 0, 10, 3, 1)
s.Metric("Count", fmt.Sprintf("%.0f", n), "+1")
}
s := newSession()
tree := s.run(app)
// The main region holds the three elements in call order.
main := tree.Children[1]
for _, el := range main.Children {
fmt.Println(el.Type)
}
Output: title slider metric
Example (CacheResource) ¶
ExampleSession_cacheResource shows the @st.cache_resource analogue: a singleton built once and shared by every session, unlike Cache which holds data and can expire.
CacheResourceClear()
builds := 0
open := func() any {
builds++
return "connection"
}
a, b := newSession(), newSession()
fmt.Println(a.CacheResource("db", open))
fmt.Println(b.CacheResource("db", open))
fmt.Println("builds:", builds)
Output: connection connection builds: 1
Example (Rerun) ¶
ExampleSession_rerun shows st.rerun's control flow: the run is abandoned at the call and the app executes again from the top, so the second pass sees the state written just before it and the discarded elements never reach the page.
app := func(s *Session) {
if !s.State.GetBool("ready", false) {
s.Text("loading…") // discarded: this pass is thrown away
s.State.Set("ready", true)
s.Rerun()
}
s.Title("Dashboard")
}
s := newSession()
tree := s.run(app)
main := tree.Children[1]
fmt.Println("elements:", len(main.Children))
fmt.Println("first:", main.Children[0].Type)
Output: elements: 1 first: title
Example (State) ¶
ExampleSession_state shows the two lifetimes an app has to reason about. State survives every rerun; a widget's value survives only as long as the app keeps rendering that widget.
app := func(s *Session) {
s.State.SetDefault("runs", 0)
s.State.Set("runs", s.State.GetInt("runs", 0)+1)
s.TextInput("Name", "anon", "name")
}
s := newSession()
s.run(app)
s.widgets["name"] = "ada" // stand-in for a browser interaction
tree := s.run(app)
fmt.Println("runs:", s.State.GetInt("runs", 0))
fmt.Println("name:", tree.Children[1].Children[0].Props["value"])
fmt.Println("keys:", s.State.Keys())
Output: runs: 2 name: ada keys: [runs]
Example (Stop) ¶
ExampleSession_stop shows st.stop: elements added before the call stay on the page and nothing after it runs.
app := func(s *Session) {
s.Title("Private area")
if !s.State.GetBool("authenticated", false) {
s.Error("Please log in")
s.Stop()
}
s.Text("secrets")
}
s := newSession()
main := s.run(app).Children[1]
for _, el := range main.Children {
fmt.Println(el.Type)
}
Output: title alert
func (*Session) Cache ¶ added in v0.2.0
Cache returns the value memoised under key, computing it with compute on the first call (or after the entry has expired) and returning the stored value on subsequent calls. The cache is process-wide and shared across sessions, so an expensive computation runs once and is reused by every rerun and every browser, mirroring Streamlit's st.cache_data.
An optional time-to-live may be supplied as the final argument; a positive TTL causes the entry to be recomputed once it has aged past the duration. A zero or omitted TTL caches for the lifetime of the process.
rows := s.Cache("report", func() any { return loadReport() }, time.Minute)
report := rows.([]Row)
Concurrent callers asking for the same missing key do not each run compute: the first caller computes while the others wait for its result. The table holds at most DefaultMaxCacheEntries entries (see CacheSetMaxEntries); when it is full the entry inserted longest ago is evicted. Derive keys that include everything the computation depends on — this port takes an explicit key rather than hashing the arguments the way Python's decorator does.
func (*Session) CacheResource ¶ added in v0.4.0
CacheResource returns the singleton registered under key, creating it with create on the first call, mirroring Streamlit's @st.cache_resource. Use it for objects that are expensive to build and safe to share — database handles, model weights, clients — rather than for data.
Unlike Session.Cache a resource has no TTL and is never evicted, so create runs exactly once per key for the lifetime of the process. create must return a value that is safe for concurrent use, because every session shares it.
db := s.CacheResource("db", func() any { return mustOpenDB() }).(*sql.DB)
func (*Session) Rerun ¶ added in v0.4.0
func (s *Session) Rerun()
Rerun abandons the current run and immediately re-executes the app function from the top, mirroring Streamlit's st.rerun. Every element added so far is discarded; State and widget values persist, so the fresh run observes any change made before the call.
It is the escape hatch for "I have just mutated state that earlier code already rendered" — the canonical example being a login form that must repaint the whole page once authentication succeeds:
if s.Button("Log in") {
s.State.Set("user", name)
s.Rerun() // repaint the page as the logged-in user
}
Like Session.Stop it is implemented by panicking with an internal sentinel and so must be called from within the app function, not a separate goroutine. A chain of reruns within a single request is capped (see maxRerunChain); an app that calls Rerun unconditionally therefore terminates with the tree from the final permitted run instead of hanging.
func (*Session) SetPageConfig ¶ added in v0.3.0
SetPageConfig sets page-level metadata for the app, mirroring Streamlit's st.set_page_config. title is the browser tab title and icon is an optional favicon (typically an emoji). The values are attached to the root of the element tree. Call it once, at the top of the app function.
func (*Session) Sidebar ¶
Sidebar returns the container for the app's sidebar region. Elements added to it render in a fixed panel beside the main content.
func (*Session) Stop ¶ added in v0.3.0
func (s *Session) Stop()
Stop immediately halts execution of the current run of the app function, mirroring Streamlit's st.stop. Elements added before the call remain on the page; nothing after it runs. It is implemented by panicking with an internal sentinel that the run loop recovers, so it must be called from within the app function (not from a separate goroutine).
if !authenticated {
s.Error("Please log in")
s.Stop() // the rest of the app does not run
}
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is a per-session key/value store that persists across reruns of the app function. It is the Go analogue of Streamlit's st.session_state and is a convenient place to keep data (counters, accumulated history, cached computations) that must survive the top-to-bottom re-execution of the app.
State is safe to use only from within a single run of the app function; the server serialises runs of a given session, so no additional locking is required by app code.
func (*State) Clear ¶ added in v0.4.0
func (s *State) Clear()
Clear removes every key from the store.
func (*State) GetBool ¶ added in v0.4.0
GetBool returns the bool stored under key, or def if absent or not a bool.
func (*State) GetFloat ¶
GetFloat returns the float64 stored under key, or def if absent or not numeric.
func (*State) GetString ¶
GetString returns the string stored under key, or def if absent or not a string.
func (*State) Has ¶ added in v0.4.0
Has reports whether key is present, mirroring `key in st.session_state`.
func (*State) Keys ¶ added in v0.4.0
Keys returns the store's keys in ascending lexical order. The order is sorted rather than map order so that iterating state is deterministic across reruns.
func (*State) SetDefault ¶ added in v0.4.0
SetDefault stores value under key only if the key is absent and reports whether it was stored. It is the analogue of Streamlit's common `if "k" not in st.session_state: st.session_state.k = v` idiom, which is how per-session state is seeded on the first of many reruns.
type UploadedFile ¶ added in v0.2.0
type UploadedFile struct {
// Name is the client-supplied filename.
Name string
// Size is the length of Data in bytes.
Size int
// Data is the file's raw content.
Data []byte
}
UploadedFile is a single file received from a Container.FileUploader. Data holds the raw bytes uploaded by the browser.