syralit

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: MIT Imports: 35 Imported by: 0

README

Syralit

Interactive data apps in Go.

CI Go Reference Go Report Card Go Version

Syralit is a Go-native framework for building interactive data apps, dashboards, and AI tool interfaces — inspired by Streamlit, designed for Go.

Write Go functions, get a live web app. No JavaScript, no HTML templates, no frontend build step.

package main

import sy "github.com/HazelnutParadise/syralit"

func main() {
    sy.App(func() {
        sy.Title("Hello Syralit")
        name := sy.TextInput("Your name")
        if name != "" {
            sy.Success("Hello, " + name + "!")
        }
    })
}

Installation

go install github.com/HazelnutParadise/syralit/cmd/syralit@latest

Requirements

  • Go 1.25+

Quick Start

syralit new myapp    # scaffold a new project
cd myapp
syralit dev          # hot reload with state preservation

Or manually:

package main

import sy "github.com/HazelnutParadise/syralit"

func main() {
    sy.App(func() {
        sy.Title("My App")
        if sy.Button("Click me") {
            sy.Balloons()
        }
    })
}
go run .
# Open http://localhost:8600

Agent Skills

The skills/ directory contains Agent Skills for building Syralit apps with AI coding assistants.

Install it into your project with the skills CLI:

npx skills add HazelnutParadise/syralit/skills

Or copy the skills/syralit-dev/ folder into your agent's skills directory manually (e.g. .claude/skills/).

Screenshots

Real screenshots captured from the runnable examples in examples/.

Showcase dashboard (examples/showcase)
Light Dark
Syralit showcase dashboard Syralit showcase dashboard dark mode
Data explorer (examples/data-explorer)
Light Dark
Syralit data explorer analysis view Syralit data explorer analysis view dark mode
Click-to-filter dashboard (examples/insyra-interactive)
Light Dark
Syralit insyra interactive dashboard Syralit insyra interactive dashboard dark mode
Data studio — upload → group → click to drill down (examples/data-studio)
Light Dark
Syralit data studio Syralit data studio dark mode
Conference registration form (examples/form-app)
Light Dark
Syralit conference registration form Syralit conference registration form dark mode

Beyond Streamlit

Things Syralit does that Streamlit can't, by leaning on Go:

// Background jobs — run work in a goroutine; the page stays responsive and the
// server pushes the result when ready (a Streamlit rerun blocks the whole app).
job := sy.Task("report", func() Report { return buildReport() }) // runs once
if job.Running() {
    sy.Spinner("Crunching…")
} else {
    render(job.Result())
}
  • sy.Task[T] — non-blocking background work with auto-push on completion.
  • sy.Shared[T] — app-wide state shared across all sessions; a Set/Update pushes a live update to every connected client (real-time collaboration).
  • sy.ArtifactCanvas — an agent-updatable canvas region rendered from a controlled DSL of reusable Syralit components. Apps opt in to a POST endpoint with bearer-token auth; new specs animate into place for every open session.
  • sy.Fragment(key, fn, sy.RunEvery(d)) — server-driven live refresh.
  • syralit build — compile the whole app (front-end + backend + your public/) into one self-contained executable; no Python, no runtime, no deps.
  • Fully offline / air-gappedsy.SetAssetURL(name, url) repoints any third-party lib (Chart.js, Leaflet, KaTeX, Plotly, …) to a self-hosted copy; drop the files in public/ and syralit build bakes everything into one binary that needs no internet or CDN (also satisfies strict CSP).
  • Automatic SSE fallback — when a WebSocket can't be established (e.g. a proxy that blocks WS upgrades), the client transparently switches to a plain HTTP transport: Server-Sent Events downstream + POST upstream. No code change.
  • sy.Handler(cfg, fn) — mount a Syralit app as a plain http.Handler inside an existing Go server (works behind http.StripPrefix sub-paths).
  • Typed state via generics (sy.State[T]) and typed sy.Task[T] results.

Features

Input Widgets
Widget Returns Description
Button bool Clickable button (true for one rerun)
TextInput string Single-line text
PasswordInput string Masked text input
TextArea string Multi-line text
NumberInput float64 Number with min/max/step
Slider float64 Range slider
RangeSlider (float64, float64) Two-handle slider returning a (low, high) range
DateSlider string Slider over a date range, returns "YYYY-MM-DD"
TimeSlider string Slider over a time range, returns "HH:MM"
SelectSlider string Discrete slider with labels
Checkbox bool Checkbox
Toggle bool Toggle switch
Radio string Radio button group
SelectBox string Dropdown (auto-searchable at 20+ items)
MultiSelect []string Multi-select dropdown
DateInput string Date picker (YYYY-MM-DD)
DatetimeInput string Date+time picker (YYYY-MM-DD HH:MM)
DateRangeInput (string, string) Start/end date pickers
TimeInput string Time picker (HH:MM)
ColorPicker string Color hex picker
FileUploader *UploadedFile File upload
FileUploaderMultiple []*UploadedFile Multi-file upload
CameraInput string Webcam capture
AudioInput string Microphone recording
ChatInput string Chat message input
Feedback string Thumbs up/down
SegmentedControl string Segmented buttons (SegmentedControlMulti[]string)
Pills string Pill-style buttons (PillsMulti[]string)
Pagination int Page selector
MenuButton string Dropdown button returning the clicked option

Plus: DownloadButton, LinkButton, PageLink, Badge.

Display

Title, Header, Subheader, Text, Textf, Markdown, Caption, Code (syntax highlighting via highlight.js), LaTeX (KaTeX), JSON (interactive tree), HTML, Image, ImageFromBytes, Audio, Video, Link, Metric (with delta indicators), Progress, Spinner, WriteStream (token-by-token streaming), Component (custom HTML/JS), IFrame, PDF (embedded viewer), Exception (styled Go error box).

Agent Artifacts

ArtifactCanvas renders a shared, animated canvas from a safe DSL. The DSL is designed for AI agents: it accepts only a curated set of reusable Syralit components, supports JSON Pointer data binding, and never exposes raw HTML, custom JS, iframes, or the internal Node protocol.

mainBoard := sy.NewArtifactStore("main", sy.ArtifactSpec{
    Version: "v1",
    Layout:  sy.ArtifactLayout{Columns: 2, Gap: 14, Padding: 16},
    Data: map[string]any{
        "summary": map[string]any{"revenue": "$42k"},
    },
    Nodes: []sy.ArtifactNode{{
        ID:        "revenue",
        Component: "metric",
        Props:     map[string]any{"label": "Revenue"},
        Bind:      map[string]string{"props.value": "/summary/revenue"},
    }},
})

notesBoard := sy.NewArtifactStore("notes", notesSpec)
auth := sy.StaticAgentKey("local-agent", sy.Secrets("AGENT_KEY"))

// One discoverable endpoint for every explicitly exposed canvas.
sy.HandleArtifactAPI(
    "/api/agent/artifacts",
    auth,
    mainBoard,
    notesBoard,
)

sy.App(func() {
    sy.ArtifactCanvas(mainBoard, sy.Height(520))
    sy.ArtifactCanvas(notesBoard, sy.Height(240))
})

Set SYRALIT_URL to the public URL printed by syralit run or syralit dev. Agents then discover the available canvases and update one by ID. The discovery response also carries a components object (builtin + custom) so an agent can tell whether an opt-in component like insyra is enabled before using it:

curl "$SYRALIT_URL/api/agent/artifacts" \
  -H "Authorization: Bearer $AGENT_KEY"

curl -X POST "$SYRALIT_URL/api/agent/artifacts" \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"artifact":"main","expected_revision":1,"spec":{"version":"v1","nodes":[{"id":"msg","component":"text","props":{"text":"Updated"}}]}}'

The update response includes a revision plus page/selector preview metadata. Browser-capable agents wait until the selected canvas has the returned data-artifact-revision and data-artifact-state="settled", then capture that element. This waits for the keyed transition, charts, images, and fonts rather than taking a screenshot mid-animation. expected_revision must match the latest discovery/current-spec response; stale writes receive 409 Conflict instead of silently overwriting a newer agent update. In hot-reload mode, the public dev server proxies /api/ to its current child; never use the ephemeral child port shown in internal diagnostics.

HandleArtifactEndpoint remains available when each canvas needs its own route or authenticator. ArtifactAPIHandler and ArtifactHandler return ordinary http.Handler values for mounting the API on another mux or port.

For user-managed keys, implement sy.AgentKeyStore and render sy.AgentKeyManager(store). Syralit provides the UI and callback contract; your app decides whether keys live in memory, a file, a database, or another secret system.

Full DSL reference: docs/artifact-dsl.md

Data
Widget Description
Table Static string table
DataFrame Sortable table; optional row selection (sy.Selectable() → returns selected indices; sy.SelectionMode("single-row") for one), sy.ColumnOrder(...) to reorder/filter columns, typed display via sy.ColConfig
DataEditor Editable table with 11 column types

Column configuration (sy.ColConfig, shared by DataFrame and DataEditor) supports types text, number, checkbox, select, date, time, datetime, link, image, progress, list, plus the display-only mini-chart columns bar_chart / line_chart (cell value is a []float64). Each column may set Format (printf-style, e.g. "$%.2f", "%d%%"), Label (header override), Help (header tooltip), Width, Min/Max/Step, and Color (chart columns). Dynamic row add/delete with sy.DynamicRows().

sy.DataEditor(headers, rows,
    sy.ColConfig(map[string]sy.ColumnConfig{
        "Score": {Type: "number", Min: 0, Max: 100},
        "Pass":  {Type: "checkbox"},
        "Grade": {Type: "select", Options: []string{"A", "B", "C"}},
    }),
    sy.DynamicRows(),
)
Charts

Built-in interactive charts powered by Chart.js:

Chart Input Description
LineChart map[string][]float64 Line chart with multiple series
BarChart map[string][]float64 Bar chart
AreaChart map[string][]float64 Filled line chart
ScatterChart map[string][][2]float64 Scatter plot with xy pairs
PieChart map[string]float64 Pie chart
DoughnutChart map[string]float64 Doughnut chart
HistogramChart []float64, bins Histogram from raw data
RadarChart labels, map[string][]float64 Radar/spider chart
GraphvizChart dot string Graphviz DOT via viz.js

Bar/area/line charts accept sy.Stacked(), sy.Horizontal() (bar), sy.Colors([]string{...}), sy.XLabels(...), and sy.ChartTitle(...).

Line/Bar/Area/Scatter/Pie charts are selectable: add sy.Selectable() and the call returns a *sy.ChartSelection (Series/Index/X/Value) when the user clicks a data point:

if sel := sy.BarChart(data, sy.Selectable(), sy.Key("sales")); sel != nil {
    sy.Textf("%s at %s = %v", sel.Series, sel.X, sel.Value)
}

With sy.RangeSelectable(), dragging across a Line/Bar/Area chart selects an x-axis range (sel.Range, Index..EndIndex, X..EndX) — the building block for time-series drill-downs:

if sel := sy.LineChart(data, sy.RangeSelectable(), sy.Key("ts")); sel != nil && sel.Range {
    sy.Textf("from %s to %s", sel.X, sel.EndX)
}

External charting library integrations (CDN-loaded, accepting JSON specs):

Chart Library Streamlit Equivalent
VegaLiteChart Vega-Lite / vega-embed st.altair_chart
PlotlyChart Plotly.js st.plotly_chart
PyplotChart SVG/PNG images st.pyplot
BokehChart BokehJS st.bokeh_chart
PydeckChart deck.gl st.pydeck_chart
Layout
// Columns (equal or weighted)
cols := sy.Columns(3)
cols[0](func() { sy.Text("Col 1") })

cols := sy.WeightedColumns(2, 1, 1)

// Tabs
tab := sy.Tabs([]string{"Tab1", "Tab2"})
tab("Tab1", func() { sy.Text("Content 1") })

// Other containers
sy.Sidebar(func() { ... })
sy.Expander("Title", func() { ... })
sy.Container(func() { ... }, sy.Border())
sy.Form("key", func() { ... }, sy.ClearOnSubmit())  // ClearOnSubmit optional
sy.Status("Loading", "running", func() { ... })
sy.Fragment("key", func() { ... })  // partial rerun
sy.Space(sy.Height(32))             // vertical whitespace
sy.Bottom(func() { ... })           // pin content to the bottom of the viewport
State & Session
// Typed state (persists across reruns)
count := sy.State("count", 0)
count.Get()
count.Set(42)

// Query parameters (SetQueryParam updates the browser URL — shareable state)
val := sy.QueryParam("page")
sy.SetQueryParam("page", "2")

// Reset a widget to its default (e.g. clear a chart selection)
sy.ResetWidget("key")

// Request context (headers, cookies, host, IP, locale) — st.context
ctx := sy.Context()
lang := ctx.Locale

// Flow control
sy.Stop()   // halt rendering
sy.Rerun()  // force rerun
Multi-Page Apps
func init() {
    sy.AddPage("Home", homePage, sy.PageIcon("🏠"), sy.PageOrder(1))
    sy.AddPage("About", aboutPage, sy.PageIcon("ℹ️"), sy.PageOrder(2))
}

func main() { sy.App(nil) }
Auth
// Login gate blocks rendering until authenticated
username := sy.LoginGate(func(user, pass string) bool {
    return user == "admin" && pass == "secret"
})

// Role-based access
user := sy.User()  // map[string]string or nil
sy.Login(map[string]string{"name": "admin", "role": "admin"})
sy.Logout()

OIDC single sign-on lives in a separate module (integrations/oidc) so its dependency tree never touches the core. Wrap the app handler and every visitor signs in through Google / Microsoft Entra / Keycloak / Auth0 / any OIDC provider; sy.User() then returns the verified claims:

import syoidc "github.com/HazelnutParadise/syralit/integrations/oidc"

handler, _ := syoidc.Protect(sy.Handler(sy.Config{}, app), syoidc.Config{
    Issuer:       "https://accounts.google.com",
    ClientID:     os.Getenv("OIDC_CLIENT_ID"),
    ClientSecret: os.Getenv("OIDC_CLIENT_SECRET"),
    RedirectURL:  "http://localhost:8600/auth/callback",
    CookieSecret: []byte(os.Getenv("COOKIE_SECRET")),
})
http.ListenAndServe(":8600", handler)
Caching
data := sy.CacheData("key", func() []Row {
    return fetchFromDB()
}, sy.TTL(5 * time.Minute))

db := sy.CacheResource("db", func() *sql.DB {
    return openDB()
})
Feedback & Notifications
sy.Success("Done!")
sy.Error("Failed!")
sy.Warning("Watch out")
sy.Info("Note")
sy.Toast("Message", "success")
sy.Balloons()
sy.Snow()
sy.Dialog("Settings", func() { ... })
Streaming (LLM Output)
sy.WriteStream(func(yield func(string)) {
    for _, word := range words {
        yield(word + " ")
        time.Sleep(30 * time.Millisecond)
    }
})
Chat UI
msgs := sy.State("msgs", []map[string]string{})
for _, m := range msgs.Get() {
    sy.ChatMessage(m["role"], func() {
        sy.Markdown(m["content"])
    })
}
if input := sy.ChatInput("Ask something..."); input != "" {
    msgs.Set(append(msgs.Get(), map[string]string{
        "role": "user", "content": input,
    }))
}
Maps
sy.Map([]sy.MapPoint{
    {Lat: 25.0330, Lon: 121.5654, Text: "Taipei 101"},
}, sy.Height(450))
Database
db := sy.Connection("mydb")
rows := sy.SQLQuery(db, "SELECT * FROM users")

Common Options

sy.Key("unique_key")        // stable widget identity
sy.DefaultValue(val)         // initial value
sy.Placeholder("hint")      // placeholder text
sy.Help("tooltip")          // help tooltip
sy.Disabled()               // disable widget
sy.Min(0), sy.Max(100)      // numeric range
sy.Step(0.5)                // numeric step
sy.Height(300), sy.Width(400)
sy.ChartTitle("Title")      // chart title
sy.Border()                 // container border
sy.Color("green")           // element color
sy.Language("go")           // code language

// Button styling (Button, LinkButton, DownloadButton)
sy.Icon("🚀")               // prefix a button label with an icon
sy.ButtonType("secondary")  // "primary" (default), "secondary", "tertiary"
sy.UseContainerWidth()      // make a button span its container

sy.Border()                 // also: bordered Metric card
sy.MinDate("2026-01-01")    // DateInput / DateRangeInput lower bound
sy.MaxDate("2026-12-31")    // DateInput / DateRangeInput upper bound

Insyra Integration

Syralit has first-class support for Insyra DataTable and DataList via a cleanly separated adapter package. The core framework never imports Insyra.

import syi "github.com/HazelnutParadise/syralit/integrations/insyra"

// DataTable (multi-column)
syi.Table(dt)                           // render DataTable
syi.Preview(dt, 5)                      // first N rows
syi.EditableTable(dt, sy.Key("edit"))   // editable DataTable
col := syi.ColumnSelect("Column", dt)   // column picker
syi.Metrics(dt, col)                    // count, mean, min, max
syi.BarChart(dt, "Category", "Value")   // chart from columns ("Category" = axis labels)
syi.LineChart(dt, "Month", "Revenue")   // all chart helpers accept sy.Option and return
syi.ScatterChart(dt, "X", "Y")          // *sy.ChartSelection when sy.Selectable() is set
syi.MultiLineChart(dt, "Month", nil)    // every numeric column as a series (st.line_chart(df))

// Click-to-filter dashboards: GroupBy chart + selection + filter
sel := syi.GroupedBarChart(dt, "Region", "Revenue", insyra.OpSum,
    sy.Selectable(), sy.Key("by_region"))
syi.Table(syi.FilterBySelection(dt, "Region", sel))  // nil selection = unfiltered
sub := syi.FilterEquals(dt, "Region", "North")       // pure data helper
edited := syi.EditableDataTable(dt, sy.Key("e"))     // edits → new *insyra.DataTable
syi.DownloadCSV("Export", dt, "data.csv")            // CSV download button
syi.RollingMeanChart(dt, "Month", "Revenue", 7)      // raw + rolling mean overlay
syi.CumSumChart(dt, "Month", "Revenue")              // cumulative sum
syi.PctChangeChart(dt, "Month", "Revenue", 1)        // percent change bars
out := syi.AddFormulaColumn(dt, "ccl")               // interactive CCL formula column

// DataList (single series) — the symmetric counterpart
syi.List(dl)                            // single-column table
syi.ListPreview(dl, 5)                  // first N values
syi.EditableList(dl, sy.Key("edl"))     // editable single column → []any
syi.ListMetrics(dl)                     // count, mean, min, max
syi.ListDescribe(dl)                    // count/mean/std/min/25%/50%/75%/max
syi.ListBarChart(dl)                    // value over index
syi.ListLineChart(dl)
syi.ListAreaChart(dl)
syi.Histogram(dl, 20)                   // distribution (list-only)

// Statistical analysis (insyra/stats), rendered in the UI
syi.Describe(dt)                              // full per-column summary table
syi.Correlation(dt, "X", "Y", "pearson")     // r + p as metrics
syi.CorrelationMatrix(dt, "pearson")         // pairwise correlation matrix
syi.LinearRegression(dt, "Y", "X1", "X2")    // R²/coeffs table + scatter
syi.TTest(dt, "A", "B", false)               // two-sample t-test

// Load a file into a DataTable (CSV / Excel / JSON)
dt := syi.UploadTable("Upload data")         // file uploader → *DataTable
dt, err := syi.ParseTable(name, bytes)       // parse bytes from any source

// Interactive transforms (non-destructive)
out := syi.FilterBuilder(dt)                 // column/op/value row filter
out := syi.CCLBuilder(dt)                    // add a computed column (CCL)

Native interactive charts beyond the built-in Chart.js layer (Sankey, word cloud, K-line, gauge, funnel, …) live in a separate opt-in subpackage, because they pull in go-echarts and (transitively) chromedp:

import syiplot "github.com/HazelnutParadise/syralit/integrations/insyra/eplot"
import "github.com/HazelnutParadise/insyra/plot"

syiplot.WordCloud(dl, "Tags")                       // no Chart.js equivalent
syiplot.EChart(plot.CreateSankeyChart(cfg, links...)) // any insyra/plot chart

syiplot.SetOffline(true) // inline echarts JS into each chart — no CDN, runs
                         // air-gapped / under strict CSP / as a `syralit build` binary
Insyra DSL — dynamic computation

Run the Insyra CLI DSL (.isr) from Go and render the result, or let agents embed a DSL script directly in an Artifact for live server-side computation. This is a separate opt-in subpackage because the DSL engine pulls in the full Insyra CLI dependency tree (cobra, database drivers, parquet/arrow, readline):

import syidsl "github.com/HazelnutParadise/syralit/integrations/insyra/insyradsl"

// Go widget: run a script (safe mode) and auto-render. Cached by script hash.
syidsl.DSL(`
newdl Q1 Q2 Q3 Q4 as quarter
newdl 42 55 61 78 as revenue
newdt quarter revenue as t
setcolnames t quarter revenue
`, syidsl.Render("bar_chart"), syidsl.Output("t"), syidsl.X("quarter"), syidsl.Y("revenue"))

res := syidsl.RunDSL(script) // low-level: inspect res.Vars / res.Output / res.Err

RunDSL runs in safe mode by default — a default-deny allowlist of pure, in-memory compute commands; load/save/db/fetch/run are rejected, and each run uses an isolated, ephemeral environment (no shared ~/.insyra state). Pass syidsl.Unrestricted() only for trusted, app-authored scripts.

Importing the package also registers an insyra Artifact component, so an agent can POST a spec that computes live instead of only binding static data:

{ID: "chart", Component: "insyra", Props: map[string]any{
    "script": "newdl North South West as region\nnewdl 12 18 9 as deals\n" +
        "newdt region deals as t\nsetcolnames t region deals",
    "render": "bar_chart", "output": "t", "x": "region", "y": "deals"}}

Configuration

syralit.toml
title = "My App"
host = "0.0.0.0"
port = 8600

[theme]
mode = "system"        # "light" | "dark" | "system"
accent = "#7C3AED"
radius = "12px"
button_radius = "999px"                 # defaults to radius
background_color = "#ffffff"
secondary_background_color = "#f8f9fb"  # widget/code/sidebar surface
text_color = "#1f2329"
link_color = "#2563eb"                  # defaults to accent
link_underline = true                   # true: always, false: never, unset: on hover
code_text_color = "#0f766e"
code_background_color = "#f1f5f9"
border_color = "#e5e7eb"
dataframe_border_color = "#e5e7eb"
dataframe_header_background_color = "#f3f4f6"
show_widget_border = true
show_sidebar_border = true
# Basic palette (badges, alerts, status colors); each of red/orange/yellow/
# blue/green/violet/gray also has <name>_background_color and <name>_text_color.
red_color = "#dc2626"
blue_background_color = "#eff6ff"
# Chart palettes (categorical drives built-in chart series colors).
chart_categorical_colors = ["#7c3aed", "#2563eb", "#16a34a"]
chart_sequential_colors = ["#f0fdfa", "#0f766e"]
chart_diverging_colors = ["#dc2626", "#f8fafc", "#2563eb"]
# Fonts: "sans-serif" | "serif" | "monospace" select the built-in Source Sans 3 /
# Source Serif 4 / Source Code Pro (embedded, served locally — no CDN); any
# other value is used as a CSS font-family list.
font = "sans-serif"
heading_font = "serif"
code_font = "monospace"
base_font_size = 16
base_font_weight = 400
heading_font_sizes = ["2rem", "1.5rem", "1.15rem"]  # h1..h6
heading_font_weights = [700, 650, 600]
code_font_size = "0.875rem"
code_font_weight = 400

[[theme.font_faces]]   # load custom fonts (otf/ttf/woff/woff2)
family = "Inter"
url = "/fonts/inter.woff2"   # public/ path or absolute URL
weight = "100 900"
style = "normal"

[theme.sidebar]        # sidebar-only overrides — every color/font/radius key
font = "sans-serif"    # above works here too (inherits main theme when unset)
accent = "#f59e0b"

[secrets]
api_key = "sk-..."
db_dsn = "postgres://..."

[server]
max_upload_size_mb = 50   # FileUploader/CameraInput cap (default 10 MB)
ssl_cert_file = "cert.pem"  # serve HTTPS when both are set
ssl_key_file = "key.pem"

[i18n]                    # localize built-in UI text
connecting = "連線中…"
loading = "載入中…"
Runtime Configuration
sy.SetPageConfig(
    sy.PageTitle("My App"),
    sy.PageLayout("wide"),
    sy.ConfigIcon("🚀"),
    sy.PrimaryColor("#ff4b4b"),
    sy.InitialSidebarState("collapsed"),
    sy.ConfigMenuItems("https://…/help", "https://…/issues", "**About** markdown"),
)

apiKey := sy.Secrets("api_key")

CLI Commands

Command Description
syralit new <name> Scaffold a new project in a new folder
syralit new . Scaffold into the current directory (no wrapper folder)
syralit dev Hot reload with state preservation
syralit run Build and run once (no watching)
syralit build [-o out] [dir] Compile to a single self-contained executable

Static Files & Bundling

Drop files in a public/ directory and they're served at the site root — public/logo.png/logo.png. In syralit dev they're served from disk; for production, syralit build folds public/ (and any assets/ overrides) into the binary via //go:embed, so the result is one executable with the front-end, backend, and all your static files — nothing to copy alongside it.

syralit build              # → ./<dir-name>[.exe], everything embedded
syralit build -o myapp .   # custom output path

You can also wire static files manually with sy.Static(fsys) (served at the root) and sy.StaticAssets(fsys) (overrides the built-in front-end assets).

Testing

sy.AppTest is a headless testing harness (the Go counterpart of Streamlit's st.testing.v1.AppTest): render without a server, simulate widget input and button clicks, and assert on the resulting tree.

at := sy.NewAppTest(func() {
    name := sy.TextInput("Name", sy.Key("name"))
    if sy.Button("Greet", sy.Key("greet")) {
        sy.Success("Hello, " + name)
    }
})
at.Run()
at.SetValue("name", "Ada")
at.Click("greet") // or at.ClickLabel("Greet")
at.Run()
// at.Texts("status") -> ["Hello, Ada"]

For a single render, sy.RenderOnce(appFn) *Node returns the UI tree directly:

tree := sy.RenderOnce(func() { sy.Metric("Users", "24,891") })
if len(tree.Find("metric")) != 1 { t.Fatal("expected a metric") }

The repo also ships a browser-level UI suite under uitest/ — a separate Go module (so its chromedp dependency never touches the framework's go.mod) that drives headless Chrome against an in-process app and asserts on real rendered behavior: widget round-trips over WebSocket, CSS visibility, canvas chart clicks, multi-file uploads, and sub-path mounting.

cd uitest && go test ./...   # requires a local Chrome/Chromium

Examples

The examples/ directory contains runnable demo apps:

Example Description
hello Minimal single-page app with basic widgets
showcase Comprehensive 6-page demo of all features
chatbot Chat UI with simulated streaming AI responses
form-app Conference registration form with validation
data-explorer 3-page sales dashboard with charts, filters, and data editing
auth-demo Authentication with LoginGate and role-based access control
agent-artifact Artifact Canvas studio with multiple live boards, preset scenarios, local compose controls, and agent endpoints
mega-demo 10-page app showcasing every feature: all widgets, charts, layout, forms, data tables, chat, maps, state
insyra-demo Insyra integration: tables, stats, transforms, file upload, native charts
insyra-charts Native go-echarts charts (Sankey/gauge/funnel/word cloud) with offline inlining
insyra-artifact Insyra DSL dynamic computation: syidsl.DSL widget and the agent-driveable insyra Artifact component
embed-scroll Themed scrollbars inside embedded Component iframes (follow light/dark)
theme-fonts Theming: built-in Source fonts, custom @font-face, palette/link/button-radius/chart colors, sidebar overrides
streamlit-parity PDF viewer, multi-file upload, collapsed sidebar, app menu, free-entry MultiSelect, clipped media
insyra-interactive Click-to-filter dashboard: selectable GroupBy chart drives an Insyra-filtered table, metrics, and deep-linkable URL state
data-studio Full upload → explore workflow: file upload, column pickers, aggregate switch, selectable GroupBy chart, drill-down detail and statistics
oidc-login OIDC single sign-on via integrations/oidc (standalone module)

Run any example:

cd examples/chatbot
go run .

Streamlit parity

Syralit covers the commonly-used Streamlit surface in idiomatic Go. See docs/STREAMLIT_PARITY.md for the full mapping and the few intentional gaps.

Changelog

See CHANGELOG.md.

License

MIT

Documentation

Index

Constants

View Source
const ConfigFileName = "syralit.toml"

ConfigFileName is the conventional per-project settings file. It is optional; when present at the project root it fills in any value not set explicitly in code or via CLI flags (precedence: flag > syralit.toml > built-in default).

Variables

This section is empty.

Functions

func AddPage

func AddPage(title string, fn func(), opts ...PageOption)

AddPage registers a page for sidebar navigation. Call it in init() so that adding a new .go file with an init+AddPage call is all that is needed to create a page — the compiled-language equivalent of Streamlit's pages/.

Pages are sorted by PageOrder (ascending), then by registration order.

func AgentKeyManager added in v0.4.0

func AgentKeyManager(store AgentKeyStore, opts ...Option) string

AgentKeyManager renders a small key-management panel using an app-provided AgentKeyStore. It returns the one-time plaintext token after creation.

func App

func App(fn func())

App starts a Syralit app with default config. It blocks until the server stops.

In single-page mode (no AddPage calls), fn is the sole page function. In multi-page mode (AddPage called in init()), fn is ignored and pages are rendered from the registry. Pass nil when using AddPage.

func ArtifactAPIHandler added in v0.4.0

func ArtifactAPIHandler(auth AgentAuthenticator, stores ...*ArtifactStore) http.Handler

ArtifactAPIHandler returns a mountable unified discovery/update handler. It can be served from another mux or port.

func ArtifactCanvas added in v0.4.0

func ArtifactCanvas(store *ArtifactStore, opts ...Option)

ArtifactCanvas renders a live artifact region. It may be used as a full page surface or embedded alongside other Syralit widgets.

func ArtifactHandler added in v0.4.0

func ArtifactHandler(store *ArtifactStore, auth AgentAuthenticator) http.Handler

ArtifactHandler returns a mountable handler for one store. It can be served from another mux or port while the ArtifactStore still broadcasts updates to the Syralit app.

func Audio

func Audio(src string, opts ...Option)

Audio renders an HTML audio player. src can be a URL or data URI. Supports sy.Autoplay(), sy.Loop(), sy.Muted().

func AudioInput

func AudioInput(label string, opts ...Option) string

AudioInput renders a microphone recording widget. Returns the recorded audio as a base64 data URI (audio/webm), or "" if nothing recorded.

func Badge

func Badge(text string, opts ...Option)

Badge renders a small colored label. Color can be "blue", "green", "red", "orange", "gray", "violet", or any CSS color string.

func Balloons

func Balloons()

Balloons renders a celebratory balloon animation.

func BokehChart

func BokehChart(spec map[string]any, opts ...Option)

BokehChart renders a Bokeh chart from a JSON spec. The spec is a map[string]any matching Bokeh's JSON document format. Rendered client-side using BokehJS (CDN).

This is the Go equivalent of Streamlit's st.bokeh_chart.

func Bottom added in v0.6.0

func Bottom(fn func())

Bottom pins its content to the bottom of the viewport (Streamlit's st.bottom) — typically a ChatInput in chat layouts. Content renders inside a fixed bar aligned with the main area.

func Button

func Button(label string, opts ...Option) bool

func CacheData

func CacheData[T any](key string, fn func() T, opts ...CacheOption) T

CacheData returns a cached value for key. If the cache is empty or expired, fn is called to compute the value. The cache is process-global (shared across sessions), which is fine for Syralit's single-user, local-app positioning.

data := sy.CacheData("csv", func() [][]string {
    return loadCSV("data.csv")
})

func CacheResource

func CacheResource[T any](key string, fn func() T) T

CacheResource returns a cached singleton for key. Unlike CacheData, the value never expires and is intended for long-lived resources like database connections, ML models, or HTTP clients.

db := sy.CacheResource("db", func() *sql.DB {
    db, _ := sql.Open("postgres", dsn)
    return db
})

func CameraInput

func CameraInput(label string, opts ...Option) string

CameraInput renders a webcam capture widget. The user clicks "Take Photo" to capture a snapshot, which is returned as a base64-encoded JPEG data URI. Returns empty string until a photo is taken.

func Caption

func Caption(text string)

func ChatInput

func ChatInput(placeholder string, opts ...Option) string

ChatInput renders a chat text input pinned to the bottom of the content area. Returns the submitted text (non-empty only on the rerun triggered by Enter).

func ChatMessage

func ChatMessage(role string, fn func(), opts ...Option)

ChatMessage renders a chat bubble with avatar and role styling. Use inside a loop over your message history:

sy.ChatMessage("user", func() { sy.Text(msg.Content) })
sy.ChatMessage("assistant", func() { sy.Markdown(msg.Content) })

func Checkbox

func Checkbox(label string, opts ...Option) bool

func ClearCache

func ClearCache(keys ...string)

ClearCache removes cached entries. With no arguments it clears all entries; with keys it clears only the specified entries.

func CloseDialog

func CloseDialog(key string)

CloseDialog closes a dialog by its key.

func Code

func Code(code string, opts ...Option)

Code renders a preformatted code block. Use Language("go") for syntax hints.

func ColorPicker

func ColorPicker(label string, opts ...Option) string

func Component

func Component(html string, opts ...Option) any

Component renders a custom HTML/JS widget. The html parameter is rendered inside an iframe. The component can communicate with Syralit by calling parent.postMessage({syralitValue: value}, "*") to set its return value. Returns the last value sent by the component, or nil.

func Connection

func Connection(name string) *sql.DB

Connection returns a cached *sql.DB for the given name. The DSN is read from Secrets(name + "_DSN") or the [connections.<name>] section of syralit.toml. The driver must be registered by importing the appropriate database/sql driver package (e.g., _ "github.com/mattn/go-sqlite3").

db := sy.Connection("mydb")
rows, _ := db.Query("SELECT * FROM users")

func Container

func Container(fn func(), opts ...Option)

Container groups widgets into a plain wrapper (useful for conditional blocks). Use Border() to render a visible border and Height(px) for a scrollable area.

func DataEditor

func DataEditor(headers []string, rows [][]any, opts ...Option) [][]any

DataEditor renders an editable data table. Returns the current rows, reflecting any edits made by the user. Each cell edit triggers a rerun. Use ColConfig() to set column types (text, number, checkbox, select).

func DataFrame

func DataFrame(headers []string, rows [][]any, opts ...Option) []int

DataFrame renders a sortable, interactive data table. Sorting is handled client-side. Rows can contain any printable values. When made selectable with sy.Selectable(), DataFrame renders a row-selection checkbox column and returns the indices (into the original rows) the user has selected; otherwise it returns nil. Selection survives client-side sorting.

func DateInput

func DateInput(label string, opts ...Option) string

func DateRangeInput

func DateRangeInput(label string, opts ...Option) (string, string)

DateRangeInput is a pair of date pickers returning the selected (start, end) dates as "YYYY-MM-DD" strings (empty until picked) — the equivalent of Streamlit's st.date_input called with a (start, end) tuple. Inside a Form it is batched and commits on submit like any other input.

func DateSlider

func DateSlider(label, minDate, maxDate string, opts ...Option) string

DateSlider is a slider over a date range, returning the picked date as a "YYYY-MM-DD" string — the equivalent of Streamlit's st.slider with date values. minDate/maxDate are "YYYY-MM-DD"; the initial value defaults to minDate (override with sy.DefaultValue("YYYY-MM-DD")). It is form-batched.

func DatetimeInput added in v0.6.0

func DatetimeInput(label string, opts ...Option) string

DatetimeInput renders a combined date-and-time picker and returns the value as "YYYY-MM-DD HH:MM" ("" until the user picks one). Supports MinDate / MaxDate ("YYYY-MM-DD" or "YYYY-MM-DDTHH:MM") bounds and DefaultValue.

func Dialog

func Dialog(title string, fn func(), opts ...Option)

Dialog renders a modal dialog overlay. Content is always rendered in the tree (for consistent widget IDs) but only visible when open. Use ShowDialog/CloseDialog to toggle, or let the user click the backdrop/×.

Key is required to identify the dialog for ShowDialog/CloseDialog.

func Divider

func Divider()

Divider renders a horizontal rule.

func DoughnutChart

func DoughnutChart(data map[string]float64, opts ...Option)

DoughnutChart renders a doughnut chart (pie with hole). Labels map to values.

func DownloadButton

func DownloadButton(label string, data []byte, filename string, opts ...Option)

DownloadButton renders a button that downloads data as a file when clicked. Data is base64-encoded and sent to the client. Use MimeType("text/csv") to set the content type.

func Echo

func Echo(code string, fn func())

Echo displays source code alongside its output. Pass the code text and a function that produces the output widgets.

func Empty

func Empty() func(func())

Empty renders nothing by default but occupies a slot in the layout. Call the returned function with a callback to populate it. Useful for replacing content across reruns.

placeholder := sy.Empty()
if ready {
    placeholder(func() { sy.Text("Data loaded") })
}

func Error

func Error(text string)

func Exception

func Exception(err error)

Exception renders a Go error in a styled, monospace error box — the equivalent of Streamlit's st.exception. A nil error renders nothing.

func Expander

func Expander(label string, fn func(), opts ...Option)

Expander renders a collapsible section. The expanded/collapsed state is tracked server-side and persists across reruns.

func Feedback

func Feedback(opts ...Option) string

Feedback renders a thumbs up/down rating widget. Returns "up", "down", or "" (no selection yet). Useful for collecting user feedback on AI responses.

func Form

func Form(key string, fn func(), opts ...Option)

Form groups widgets so their changes are batched and only sent when the user clicks FormSubmitButton. Inside a Form, widget changes do not trigger reruns.

func FormSubmitButton

func FormSubmitButton(label string, opts ...Option) bool

FormSubmitButton renders a submit button inside a Form. Returns true on the single rerun triggered by form submission.

func Fragment

func Fragment(key string, fn func(), opts ...Option)

Fragment wraps a function so that widget changes inside it only re-run this function, not the entire app. This improves performance for complex apps with independent sections.

sy.Fragment("chart-section", func() {
    x := sy.Slider("X", sy.Min(0), sy.Max(100), sy.Key("x"))
    sy.LineChart([]float64{float64(x), float64(x*2)})
})

func GetOption added in v0.6.0

func GetOption(key string) any

GetOption returns a resolved configuration value by key: "title", "server.host", "server.port", "server.max_upload_size_mb", "theme.mode", "theme.accent", "theme.radius". Unknown keys return nil. Values reflect the running server's effective config (code > syralit.toml > defaults).

func GraphvizChart

func GraphvizChart(dot string, opts ...Option)

GraphvizChart renders a Graphviz DOT graph using viz.js (CDN).

sy.GraphvizChart(`digraph { A -> B -> C; B -> D; }`)

func HTML

func HTML(html string)

HTML renders raw HTML content directly. Use with care — user-supplied content should be sanitized before passing to this function.

func HandleArtifactAPI added in v0.4.0

func HandleArtifactAPI(path string, auth AgentAuthenticator, stores ...*ArtifactStore)

HandleArtifactAPI registers one discovery and update endpoint for several stores on the Syralit app server. GET discovers stores; POST selects a store with the request's "artifact" field.

func HandleArtifactEndpoint added in v0.4.0

func HandleArtifactEndpoint(path string, store *ArtifactStore, auth AgentAuthenticator)

HandleArtifactEndpoint registers one opt-in endpoint on the Syralit app server. POST replaces the store and GET returns its current spec and preview metadata.

func Handler added in v0.6.0

func Handler(cfg Config, fn func()) http.Handler

Handler returns the app as an http.Handler, so a Syralit app can be mounted inside an existing Go HTTP server instead of owning the process:

mux.Handle("/dashboard/", http.StripPrefix("/dashboard", sy.Handler(sy.Config{}, myApp)))

Config resolution matches Run (syralit.toml, then defaults); Host/Port are ignored since the caller owns the listener.

func Header(text string)

func HistogramChart

func HistogramChart(data []float64, bins int, opts ...Option)

HistogramChart renders a histogram from raw data values. The bins parameter sets the number of bins (defaults to 10 if zero).

func IFrame

func IFrame(url string, opts ...Option)

IFrame renders an external URL in an iframe.

func Image

func Image(src string, opts ...Option)

Image renders an image. src can be a URL or data URI. Use Alt("desc"), Width(300), ImageCaption("caption") options.

func ImageFromBytes

func ImageFromBytes(data []byte, opts ...Option)

ImageFromBytes renders an image from raw bytes. The MIME type should be specified via MimeType("image/png") or similar; defaults to image/png.

func Info

func Info(text string)

func JSON

func JSON(data any, opts ...Option)

JSON renders a formatted JSON viewer for any serializable value. JSON renders data as an interactive, collapsible tree. It is fully expanded by default; pass sy.DefaultValue(false) to start collapsed.

func LaTeX

func LaTeX(formula string)

LaTeX renders a mathematical formula using KaTeX (loaded from CDN on first use). The formula string should use LaTeX syntax without delimiters.

func Link(text, url string)

Link renders a clickable hyperlink that opens in a new tab.

func LinkButton

func LinkButton(label, url string, opts ...Option)

LinkButton renders a button-styled hyperlink that opens in a new tab.

func Login

func Login(user map[string]string)

Login sets the current session's authenticated user. Call this after validating credentials.

func LoginGate

func LoginGate(check func(username, password string) bool) string

LoginGate renders a login form and blocks the rest of the app until the user authenticates. The check function receives (username, password) and returns true if the credentials are valid. Returns the logged-in username.

user := sy.LoginGate(func(u, p string) bool {
    return u == "admin" && p == sy.Secrets("ADMIN_PASS")
})
sy.Title("Welcome, " + user)

func Logout

func Logout()

Logout clears the current session's authenticated user.

func Map

func Map(points []MapPoint, opts ...Option)

Map renders an interactive map with markers using Leaflet.js (CDN). Points are displayed as markers with optional popup text.

sy.Map([]sy.MapPoint{
    {Lat: 25.033, Lon: 121.565, Text: "Taipei 101"},
    {Lat: 25.047, Lon: 121.517, Text: "Taipei Main Station"},
}, sy.Height(400))

func Markdown

func Markdown(text string)
func MenuButton(label string, options []string, opts ...Option) string

MenuButton renders a button that opens a dropdown of options and returns the clicked option for exactly one rerun ("" otherwise) — like Button, but with a choice attached.

func Metric

func Metric(label, value string, opts ...Option)

Metric renders a big-number metric with optional delta indicator. Use Delta("1.2 °F") and DeltaColor("inverse") options.

func MultiSelect

func MultiSelect(label string, options []string, opts ...Option) []string
func Navigation(pages []Page) string

Navigation provides a declarative way to define multi-page apps inline. It registers pages, renders the active one, and returns the active page title. Unlike AddPage (which is called in init()), Navigation is called inside the app function and can be used with dynamic page lists.

active := sy.Navigation([]sy.Page{
    {Title: "Home", Fn: homePage, Icon: "🏠"},
    {Title: "Settings", Fn: settingsPage, Icon: "⚙️"},
})

func NumberInput

func NumberInput(label string, opts ...Option) float64

func PDF added in v0.6.0

func PDF(src string, opts ...Option)

PDF embeds a PDF viewer (the browser's built-in renderer). src can be a URL, a path served by the app (e.g. from public/), or a data URI. Use sy.Height(800) to change the viewer height (default 600).

func PageLink(label string, page string, opts ...Option)

PageLink renders a navigation link to another page in the app (or an external URL). When clicked for an internal page, a page_change is sent.

func Pagination

func Pagination(totalPages int, opts ...Option) int

Pagination renders a page selector for paginating data. Returns the current page number (1-based). totalPages is the total number of pages.

func PasswordInput

func PasswordInput(label string, opts ...Option) string

PasswordInput renders a password text input (masked characters).

func Pills

func Pills(label string, options []string, opts ...Option) string

func PillsMulti added in v0.1.1

func PillsMulti(label string, options []string, opts ...Option) []string

PillsMulti is the multi-select form of Pills: the user can toggle any number of options, and it returns the selected set (st.pills selection_mode="multi").

func PlotlyChart

func PlotlyChart(spec map[string]any, opts ...Option)

PlotlyChart renders a Plotly chart from a figure spec. The spec is a map[string]any matching the Plotly JSON schema (data + layout). Rendered client-side using Plotly.js (CDN).

This is the Go equivalent of Streamlit's st.plotly_chart — Plotly figures in Python serialize to JSON, so accepting the JSON spec directly provides the same capability.

sy.PlotlyChart(map[string]any{
    "data": []map[string]any{{
        "x": []string{"giraffes", "orangutans", "monkeys"},
        "y": []float64{20, 14, 23},
        "type": "bar",
    }},
    "layout": map[string]any{"title": "Animals"},
})

func Popover

func Popover(label string, fn func(), opts ...Option)

Popover renders a button that shows a floating panel with the content produced by fn.

func Progress

func Progress(value float64, text ...string)

Progress renders a progress bar. value is 0.0 to 1.0. Progress draws a progress bar for a value in [0,1]. An optional text label is shown above the bar (st.progress text=).

func PydeckChart

func PydeckChart(spec map[string]any, opts ...Option)

PydeckChart renders a deck.gl 3D map visualization from a JSON spec. The spec is a map[string]any matching deck.gl's JSON schema. Rendered client-side using deck.gl (CDN).

This is the Go equivalent of Streamlit's st.pydeck_chart — PyDeck is a Python API that generates deck.gl JSON specs.

sy.PydeckChart(map[string]any{
    "initialViewState": map[string]any{
        "latitude": 37.76, "longitude": -122.4,
        "zoom": 11, "pitch": 50,
    },
    "layers": []map[string]any{{
        "@@type": "HexagonLayer",
        "data": "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf-bike-parking.json",
        "getPosition": "@@=[lng, lat]",
        "radius": 200,
        "elevationScale": 4,
        "extruded": true,
    }},
})

func PyplotChart

func PyplotChart(data string, opts ...Option)

PyplotChart renders a static chart image from raw PNG/SVG bytes. This is the Go equivalent of Streamlit's st.pyplot — in Python, matplotlib figures are exported as images. In Go, any charting library that can export PNG or SVG can be used.

The format is auto-detected: if data starts with "<svg" it is treated as inline SVG; otherwise it is treated as a base64-encoded PNG data URI.

// From SVG string:
sy.PyplotChart(svgString)
// From PNG bytes:
sy.PyplotChart(base64.StdEncoding.EncodeToString(pngBytes))

func QueryParam

func QueryParam(key string) string

QueryParam returns a single URL query parameter value.

func QueryParams

func QueryParams() map[string]string

QueryParams returns a copy of the URL query parameters from the current session's WebSocket connection. Useful for deep linking and sharing app state via URL.

params := sy.QueryParams()
filter := params["filter"]

func RadarChart

func RadarChart(labels []string, data map[string][]float64, opts ...Option)

RadarChart renders a radar/spider chart from named series.

func Radio

func Radio(label string, options []string, opts ...Option) string

func RangeSlider

func RangeSlider(label string, min, max float64, opts ...Option) (float64, float64)

RangeSlider is a two-handle slider returning the selected (low, high) range — the equivalent of Streamlit's st.slider called with a tuple value. The initial range defaults to [min, max]; override with sy.DefaultValue([2]float64{lo, hi}). Inside a Form it is batched and commits on submit like any other input.

func RegisterArtifactComponent added in v0.5.0

func RegisterArtifactComponent(name string, compiler ArtifactComponentCompiler)

RegisterArtifactComponent registers a custom artifact component compiler under name, making <name> usable as an ArtifactNode.Component in any ArtifactSpec. It is intended to be called from an integration package's init (for example, the Insyra integration registers "insyra").

It panics on an empty name, a nil compiler, a name that collides with a built-in component, or a name already registered — all of which are program wiring errors that should surface at startup rather than at compile time.

func RegisterArtifactComponentInfo added in v0.5.0

func RegisterArtifactComponentInfo(name string, fn func() any)

RegisterArtifactComponentInfo attaches optional discovery metadata to a custom component. fn is called for each discovery request and must return a JSON-serializable value (or nil to contribute nothing); the result appears under the discovery response's components.capabilities[name]. Integrations use it to advertise live capabilities — e.g. the Insyra component reports the safe DSL command catalog for the linked Insyra version.

It panics on an empty name or nil fn. Order relative to RegisterArtifactComponent does not matter.

func Rerun

func Rerun()

Rerun triggers an immediate re-execution of the app function. The current execution is halted (like Stop) and the session is flagged for re-rendering.

func ResetWidget added in v0.7.0

func ResetWidget(key string)

ResetWidget deletes a widget's stored value (by its sy.Key), reverting it to its default on this rerun — the counterpart of Streamlit's `del st.session_state[key]`. Useful for clearing a chart selection or an input programmatically.

func Run

func Run(cfg Config, fn func()) error

Run starts a Syralit app with explicit config. Values left unset are filled from syralit.toml in the working directory if present, then by defaults.

func RunDev

func RunDev(opts DevOptions) error

RunDev starts the hot reload supervisor. The supervisor owns the outward port and the browser connections for its whole lifetime ("the app never stops"), while the user's program runs as a child process that is rebuilt and restarted on file changes. Session state is carried across restarts (SPEC §10.3).

func SQLQuery

func SQLQuery(db *sql.DB, query string, args ...any) ([]string, [][]any)

SQLQuery executes a SQL query and returns the results as headers and rows, ready to pass to DataFrame or DataEditor.

func Secrets

func Secrets(key string) string

Secrets returns a secret value from the [secrets] section of syralit.toml, falling back to an environment variable of the same name. This lets apps keep API keys out of source code.

apiKey := sy.Secrets("OPENAI_API_KEY")

func SegmentedControl

func SegmentedControl(label string, options []string, opts ...Option) string

SegmentedControl renders a row of mutually exclusive buttons. Returns the selected option string. Similar to Radio but rendered as a single bar.

func SegmentedControlMulti added in v0.1.1

func SegmentedControlMulti(label string, options []string, opts ...Option) []string

SegmentedControlMulti is the multi-select form of SegmentedControl.

func SelectBox

func SelectBox(label string, options []string, opts ...Option) string

func SelectSlider

func SelectSlider(label string, options []string, opts ...Option) string

SelectSlider renders a slider that snaps to labelled options, returning the selected label string. options must have at least 2 elements.

func SetAssetURL added in v0.2.0

func SetAssetURL(name, url string)

SetAssetURL overrides where a named front-end library is loaded from. Names: chartjs, leaflet_js, leaflet_css, katex_js, katex_css, highlight_js, highlight_css, highlight_css_dark, viz, vega, vega_lite, vega_embed, plotly, bokeh, deckgl, mapbox_js, mapbox_css.

sy.SetAssetURL("chartjs", "/chart.umd.min.js") // served from public/

func SetPageConfig

func SetPageConfig(opts ...PageConfigOption)

SetPageConfig configures page-level settings such as the browser tab title and content layout. Call this at the top of your page function.

func SetQueryParam added in v0.6.0

func SetQueryParam(key, value string)

SetQueryParam sets (or, with value "", removes) a URL query parameter. The browser's address bar updates after this rerun via history.replaceState, so app state becomes shareable as a link.

func SetUserResolver added in v0.7.0

func SetUserResolver(fn func(RequestContext) map[string]string)

SetUserResolver installs a function that maps a new session's request context to an authenticated user (nil = anonymous). It runs once per session, when the WebSocket or SSE connection is established. Intended for auth middleware such as integrations/oidc; most apps use LoginGate instead.

func ShowDialog

func ShowDialog(key string)

ShowDialog opens a dialog by its key.

func Sidebar(fn func())

Sidebar adds user-defined content to the sidebar (below the page links). In single-page mode this also causes the sidebar to appear.

func Slider

func Slider(label string, min, max float64, opts ...Option) float64

func Snow

func Snow()

Snow renders a falling snow animation.

func Space added in v0.6.0

func Space(opts ...Option)

Space inserts vertical whitespace (default 16px). Use sy.Height(px) for a custom amount or sy.Width(px) for horizontal spacing inside columns.

func Spinner

func Spinner(text ...string)

Spinner renders a loading indicator with optional text.

func SpinnerWith added in v0.6.0

func SpinnerWith(opts []Option, text ...string)

SpinnerWith renders a spinner with options, e.g. sy.ShowTime().

func Static

func Static(fsys fs.FS)

Static mounts a filesystem whose files are served at the site root, so an embedded public/ directory becomes reachable at "/...". Call it before App or Run. Multiple calls stack (first match wins); the reserved /_syralit/* routes always take precedence, and "/" always renders the app shell.

//go:embed all:public
var public embed.FS

func main() {
    sub, _ := fs.Sub(public, "public")
    sy.Static(sub)
    sy.App(myApp)
}

The `syralit build` command writes this wiring for you automatically.

func StaticAssets

func StaticAssets(fsys fs.FS)

StaticAssets overlays a filesystem on the built-in front-end assets served at /_syralit/assets/. A file here (e.g. a custom runtime.css) shadows the framework's copy — the production equivalent of `syralit dev`'s assets/ dir.

func Status

func Status(label, state string, fn func())

Status renders a collapsible status container with a state indicator. state is "running", "complete", or "error". While "running", a spinner is shown next to the label.

sy.Status("Loading data", "running", func() {
    sy.Text("Fetching from API...")
    sy.Progress(0.5)
})

func Stop

func Stop()

Stop halts the current rerun early. Widgets rendered so far are kept. Useful for conditional guards:

if !loggedIn { sy.Warning("Please log in"); sy.Stop() }

func Subheader

func Subheader(text string)

func Success

func Success(text string)

func SwitchPage

func SwitchPage(title string)

SwitchPage programmatically navigates to a different page. The current rerun is stopped and the next render will show the target page.

func Table

func Table(headers []string, rows [][]string)

Table renders a static data table.

func Tabs

func Tabs(labels []string, opts ...Option) func(string, func())

Tabs creates a tabbed container. It returns a function to define each tab's content. The active tab is tracked server-side. All tab content is rendered and sent; the client shows only the active tab.

func Text

func Text(text string)

func TextArea

func TextArea(label string, opts ...Option) string

func TextInput

func TextInput(label string, opts ...Option) string

func Textf

func Textf(format string, a ...any)

func TimeInput

func TimeInput(label string, opts ...Option) string

func TimeSlider added in v0.1.1

func TimeSlider(label, minTime, maxTime string, opts ...Option) string

TimeSlider is a slider over a time-of-day range, returning "HH:MM" — the time-valued form of Streamlit's st.slider. minTime/maxTime are "HH:MM"; the initial value defaults to minTime. Use sy.Step (minutes) for the increment (default 15). It is form-batched.

func Title

func Title(text string)

func Toast

func Toast(text string, levelAndIcon ...string)

Toast shows a brief notification that auto-dismisses. The optional variadic args are, in order, the level ("info", "success", "warning", "error") and an icon (emoji or short string) shown before the text:

sy.Toast("Saved")
sy.Toast("Done!", "success")
sy.Toast("Launched", "success", "🚀")

func Toggle

func Toggle(label string, opts ...Option) bool

func User

func User() map[string]string

User returns the current session's authenticated user info. Returns nil if no user is logged in.

func VegaLiteChart

func VegaLiteChart(spec map[string]any, opts ...Option)

VegaLiteChart renders a Vega-Lite chart from a spec. The spec is a map[string]any matching the Vega-Lite JSON schema. The chart is rendered client-side using the Vega-Lite JavaScript library (CDN).

This is the Go equivalent of Streamlit's st.altair_chart — Altair is a Python API that generates Vega-Lite JSON specs, so accepting the spec directly provides the same capability.

sy.VegaLiteChart(map[string]any{
    "mark": "bar",
    "encoding": map[string]any{
        "x": map[string]any{"field": "category", "type": "nominal"},
        "y": map[string]any{"field": "value", "type": "quantitative"},
    },
    "data": map[string]any{
        "values": []map[string]any{
            {"category": "A", "value": 28},
            {"category": "B", "value": 55},
        },
    },
})

func Video

func Video(src string, opts ...Option)

Video renders an HTML video player. src can be a URL or data URI. Use Width(640) to constrain the player width; supports Autoplay/Loop/Muted.

func Warning

func Warning(text string)

func Write

func Write(args ...any)

Write renders any value: strings are treated as Markdown, errors as Error blocks, and everything else is formatted as JSON.

func WriteStream

func WriteStream(fn func(yield func(string)), opts ...Option)

WriteStream renders text that streams in token by token. The function receives a yield callback; call it with each text chunk. Useful for displaying LLM responses as they arrive.

sy.WriteStream(func(yield func(string)) {
    for token := range llm.Stream(prompt) {
        yield(token)
    }
})

Types

type AgentAuthenticator added in v0.4.0

type AgentAuthenticator interface {
	AuthenticateAgent(ctx context.Context, token string) (AgentPrincipal, bool, error)
}

AgentAuthenticator verifies a bearer token presented to an artifact endpoint.

func StaticAgentKey added in v0.4.0

func StaticAgentKey(name, token string) AgentAuthenticator

StaticAgentKey creates an authenticator backed by one app-provided token.

type AgentKeyInfo added in v0.4.0

type AgentKeyInfo struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	CreatedAt time.Time `json:"created_at,omitempty"`
}

AgentKeyInfo is display metadata for an agent API key. It must not contain the plaintext token.

type AgentKeyStore added in v0.4.0

type AgentKeyStore interface {
	AgentAuthenticator
	ListAgentKeys(ctx context.Context) ([]AgentKeyInfo, error)
	CreateAgentKey(ctx context.Context, name string) (plainToken string, info AgentKeyInfo, err error)
	RevokeAgentKey(ctx context.Context, id string) error
}

AgentKeyStore lets apps provide their own API-key persistence while Syralit supplies the management UI.

type AgentPrincipal added in v0.4.0

type AgentPrincipal struct {
	ID   string `json:"id"`
	Name string `json:"name,omitempty"`
}

AgentPrincipal identifies the authenticated agent caller.

type AppTest added in v0.6.0

type AppTest struct {

	// Root is the UI tree produced by the most recent Run (nil before).
	Root *Node
	// contains filtered or unexported fields
}

AppTest runs an app function headlessly for testing — the Go counterpart of Streamlit's st.testing.v1.AppTest. It renders the UI tree without a server or browser, lets the test set widget values and click buttons, and exposes the resulting tree for assertions.

at := sy.NewAppTest(func() {
    name := sy.TextInput("Name", sy.Key("name"))
    if sy.Button("Greet", sy.Key("greet")) {
        sy.Success("Hello, " + name)
    }
})
at.Run()
at.SetValue("name", "Ada")
at.Click("greet")
at.Run()
if len(at.FindAll("status")) == 0 { t.Fatal("no greeting") }

Widgets addressed by test code should use sy.Key so their IDs are stable.

func NewAppTest added in v0.6.0

func NewAppTest(fn func()) *AppTest

NewAppTest wraps an app function for headless testing. In multi-page apps pass nil and use SwitchToPage.

func (*AppTest) Click added in v0.6.0

func (t *AppTest) Click(key string) *AppTest

Click registers a button press by widget ID; the button returns true during the next Run only.

func (*AppTest) ClickLabel added in v0.6.0

func (t *AppTest) ClickLabel(label string) error

ClickLabel finds a button by its visible label in the last rendered tree and registers a press. Run must have been called first.

func (*AppTest) FindAll added in v0.6.0

func (t *AppTest) FindAll(nodeType string) []*Node

FindAll returns every node of the given type in the last rendered tree, depth-first.

func (*AppTest) FindByLabel added in v0.6.0

func (t *AppTest) FindByLabel(nodeType, label string) *Node

FindByLabel returns the first node of the given type whose "label" prop equals label, or nil.

func (*AppTest) Run added in v0.6.0

func (t *AppTest) Run() *Node

Run executes one rerun (exactly like a browser-triggered rerun, including one-shot button semantics) and stores the produced tree in Root.

func (*AppTest) SetValue added in v0.6.0

func (t *AppTest) SetValue(key string, value any) *AppTest

SetValue sets a widget's value by its ID (the sy.Key of the widget). The change takes effect on the next Run, like a browser interaction.

func (*AppTest) SwitchToPage added in v0.6.0

func (t *AppTest) SwitchToPage(title string) *AppTest

SwitchToPage sets the active page (multi-page apps) for subsequent Runs.

func (*AppTest) Texts added in v0.6.0

func (t *AppTest) Texts(nodeType string) []string

Texts returns the "text" prop of every node of the given type, in render order — convenient for asserting on Title/Text/Success/Error output.

func (*AppTest) Value added in v0.6.0

func (t *AppTest) Value(key string) any

Value returns the currently stored value for a widget ID.

type ArtifactComponentCompiler added in v0.5.0

type ArtifactComponentCompiler func(node ArtifactNode, data map[string]any) (*Node, error)

ArtifactComponentCompiler compiles a custom artifact component into a render Node. It receives the raw ArtifactNode and the spec-level Data map, and must return a single Node whose Type is one the client runtime already renders (e.g. "dataframe", "table", "bar_chart", "line_chart", "pie_chart", "metric", "text"). The core applies the node's ID and layout after the compiler returns, so the compiler owns only its own props validation and construction. Returning an error fails the whole artifact compile.

Registered components let optional integrations extend the artifact DSL without the core package importing them. This keeps the core/integration boundary intact: the Insyra integration, for example, registers an "insyra" component that runs an Insyra DSL script server-side, while the core package never imports Insyra.

type ArtifactLayout added in v0.4.0

type ArtifactLayout struct {
	Columns int    `json:"columns,omitempty"`
	Gap     int    `json:"gap,omitempty"`
	Padding int    `json:"padding,omitempty"`
	Mode    string `json:"mode,omitempty"`
}

ArtifactLayout controls the canvas-level responsive layout.

type ArtifactLayoutItem added in v0.4.0

type ArtifactLayoutItem struct {
	ColumnSpan int `json:"column_span,omitempty"`
	RowSpan    int `json:"row_span,omitempty"`
}

ArtifactLayoutItem controls a single child inside an ArtifactCanvas.

type ArtifactNode added in v0.4.0

type ArtifactNode struct {
	ID        string             `json:"id"`
	Component string             `json:"component"`
	Props     map[string]any     `json:"props,omitempty"`
	Bind      map[string]string  `json:"bind,omitempty"`
	Layout    ArtifactLayoutItem `json:"layout,omitempty"`
	Children  []ArtifactNode     `json:"children,omitempty"`
}

ArtifactNode describes one safe component instance in an artifact.

type ArtifactPlacement added in v0.4.0

type ArtifactPlacement struct {
	Page     string `json:"page,omitempty"`
	URL      string `json:"url,omitempty"`
	CanvasID string `json:"canvas_id"`
	Selector string `json:"selector"`
}

ArtifactPlacement identifies one observed ArtifactCanvas in the rendered app. Page is empty for a single-page app.

type ArtifactSpec added in v0.4.0

type ArtifactSpec struct {
	Version string         `json:"version"`
	Layout  ArtifactLayout `json:"layout,omitempty"`
	Data    map[string]any `json:"data,omitempty"`
	Nodes   []ArtifactNode `json:"nodes"`
}

ArtifactSpec is the safe, agent-friendly DSL for rendering a dynamic canvas. It intentionally maps to a curated subset of Syralit components rather than exposing the internal Node protocol as a public API.

type ArtifactStore added in v0.4.0

type ArtifactStore struct {
	// contains filtered or unexported fields
}

ArtifactStore holds one shared artifact. A Set broadcasts a rerun so every active browser session sees the latest canvas.

func NewArtifactStore added in v0.4.0

func NewArtifactStore(name string, initial ArtifactSpec) *ArtifactStore

NewArtifactStore creates a shared artifact store. Invalid initial specs are represented as an error node so app startup remains recoverable.

func (*ArtifactStore) Name added in v0.4.0

func (s *ArtifactStore) Name() string

Name returns the artifact store name.

func (*ArtifactStore) Revision added in v0.4.0

func (s *ArtifactStore) Revision() uint64

Revision returns the monotonically increasing revision of the current spec. Agents can use it to wait until the browser has finished rendering an update.

func (*ArtifactStore) Set added in v0.4.0

func (s *ArtifactStore) Set(spec ArtifactSpec) error

Set replaces the artifact with a validated spec and broadcasts a live rerun.

func (*ArtifactStore) Spec added in v0.4.0

func (s *ArtifactStore) Spec() ArtifactSpec

Spec returns a copy of the current artifact spec.

type CacheOption

type CacheOption func(*cacheOpts)

CacheOption configures caching behavior. See TTL.

func TTL

func TTL(d time.Duration) CacheOption

TTL sets the time-to-live for cached data. After this duration the cached value expires and fn is re-invoked on the next call.

type ChartSelection added in v0.6.0

type ChartSelection struct {
	Series string
	Index  int
	X      string
	Value  float64

	// Range selection (sy.RangeSelectable() + drag): Range is true and
	// Index..EndIndex / X..EndX span the dragged x-axis interval.
	Range    bool
	EndIndex int
	EndX     string
}

ChartSelection is the point a user clicked on a selectable chart (see sy.Selectable() on LineChart/BarChart/AreaChart/ScatterChart/PieChart). Series is the series (or pie slice) name, Index the point's position along the x axis (or slice index), X its label, and Value the y (or slice) value. The selection persists across reruns until the user clicks another point.

func AreaChart

func AreaChart(data map[string][]float64, opts ...Option) *ChartSelection

AreaChart renders an area chart (filled line chart) from named series. With sy.Selectable(), the chart reports the clicked point (nil until then).

func BarChart

func BarChart(data map[string][]float64, opts ...Option) *ChartSelection

BarChart renders a bar chart from named series. With sy.Selectable(), the chart reports the clicked bar (nil until then).

func LineChart

func LineChart(data map[string][]float64, opts ...Option) *ChartSelection

LineChart renders a line chart from named series.

sy.LineChart(map[string][]float64{
    "Revenue": {10, 20, 30, 25, 35},
    "Cost":    {5, 8, 12, 10, 15},
})

With sy.Selectable(), the chart reports the clicked point (nil until then).

func PieChart

func PieChart(data map[string]float64, opts ...Option) *ChartSelection

PieChart renders a pie chart from labelled values.

sy.PieChart(map[string]float64{
    "Go": 45,
    "Python": 35,
    "Rust": 20,
})

func ScatterChart

func ScatterChart(data map[string][][2]float64, opts ...Option) *ChartSelection

ScatterChart renders a scatter plot. Each series maps to a slice of [x, y] coordinate pairs.

sy.ScatterChart(map[string][][2]float64{
    "Group A": {{1, 2}, {3, 4}, {5, 6}},
})

type Column

type Column func(fn func())

Column renders children into one column of a Columns layout.

func Columns

func Columns(n int, opts ...Option) []Column

Columns creates n side-by-side columns. Call each returned Column with a callback to populate it.

func WeightedColumns

func WeightedColumns(weights ...float64) []Column

WeightedColumns creates columns with custom widths specified as fractions. Example: WeightedColumns(2, 1) creates a 2:1 split (66%/33%).

type ColumnConfig

type ColumnConfig struct {
	Type    string   // column type (see above), incl. "bar_chart" / "line_chart"
	Options []string // for "select" type: dropdown options
	Width   int      // optional column width in pixels
	Min     float64  // for "number" or "progress": minimum value
	Max     float64  // for "number" or "progress": maximum value
	Step    float64  // for "number": editor step
	Format  string   // printf-style display format for numbers, e.g. "$%.2f", "%d%%"
	Label   string   // override the column header text
	Help    string   // header tooltip
	Color   string   // line/bar chart column color (CSS color)
}

ColumnConfig defines the type and options for a DataEditor column. Supported types: "text", "number", "checkbox", "select", "date", "time", "datetime", "link", "image", "progress", "list".

type Config

type Config struct {
	Title string
	Host  string
	Port  int
	Theme Theme

	// MaxUploadSizeMB caps FileUploader/CameraInput payloads, in megabytes.
	// 0 means the default (10 MB). Configurable via [server] max_upload_size_mb
	// in syralit.toml.
	MaxUploadSizeMB int

	// SSLCertFile / SSLKeyFile serve the app over HTTPS when both are set
	// (PEM files). Configurable via [server] ssl_cert_file / ssl_key_file.
	SSLCertFile string
	SSLKeyFile  string

	// UIStrings overrides the framework's built-in UI text (localization).
	// Known keys: "connecting", "loading", "add_new", "file_too_large",
	// "menu", "menu_get_help", "menu_report_bug", "menu_about".
	// Configurable via the [i18n] table in syralit.toml.
	UIStrings map[string]string
}

Config controls the dev server.

type DevOptions

type DevOptions struct {
	Dir       string // project directory to build & watch (default ".")
	Target    string // build target package (default Dir)
	Host      string // outward bind host (default 127.0.0.1)
	Port      int    // outward port (default 8600)
	Title     string // page title
	AssetsDir string // optional: serve front-end assets from disk and hot-reload them
	PublicDir string // optional: serve user static files (public/) from disk at site root
	Theme     Theme
}

DevOptions configures the hot reload supervisor.

type FontFace added in v0.6.0

type FontFace struct {
	Family       string // font family name to register
	URL          string // font file location
	Weight       string // optional, e.g. "400" or a range "200 900"
	Style        string // optional: "normal" | "italic" | "oblique"
	UnicodeRange string // optional, e.g. "U+0000-00FF"
}

FontFace declares a custom font to load (rendered as CSS @font-face), so Font / HeadingFont / CodeFont can reference families that are not installed on the visitor's machine. OTF, TTF, WOFF and WOFF2 sources work; URL may be an absolute URL or a path served by the app (e.g. from public/).

type MapPoint

type MapPoint struct {
	Lat   float64
	Lon   float64
	Text  string  // optional popup text
	Size  float64 // optional marker radius in px (renders a circle marker)
	Color string  // optional marker color (CSS color)
}

MapPoint represents a single marker on a Map widget.

type Node

type Node struct {
	ID       string         `json:"id,omitempty"`
	Type     string         `json:"type"`
	Props    map[string]any `json:"props,omitempty"`
	Children []*Node        `json:"children,omitempty"`
}

Node is one element in the UI tree that a rerun produces. The whole tree is serialized to JSON and sent to the browser, where the client runtime renders and reconciles it. See docs/event-protocol — Type drives which DOM element the client builds, Props carries its attributes, and ID is the stable widget key.

func RenderOnce

func RenderOnce(appFn func()) *Node

RenderOnce executes appFn once in a fresh, isolated session and returns the root Node of the UI tree it produces. No server is started and no socket is opened — it is meant for unit-testing widgets and integrations. Walk the result with Node.Find / Node.Children. Note: it renders appFn directly and does not consult pages registered via AddPage.

func (*Node) Find

func (n *Node) Find(typ string) []*Node

Find returns every descendant of the given type (depth-first, including n itself if it matches). It's a convenience for tests built on RenderOnce.

type Option

type Option func(*widgetOpts)

Option configures a widget. See Key, Min, Max, Step, Placeholder, etc.

func AcceptNewOptions added in v0.6.0

func AcceptNewOptions() Option

AcceptNewOptions lets a MultiSelect accept values typed by the user in addition to the predefined options.

func Alt

func Alt(v string) Option

func Autoplay added in v0.1.1

func Autoplay() Option

Autoplay / Loop / Muted control Audio and Video playback.

func Avatar added in v0.1.1

func Avatar(v string) Option

Avatar sets a custom avatar (emoji or image URL) for a ChatMessage.

func Border

func Border() Option

func ButtonType

func ButtonType(v string) Option

ButtonType selects a button's visual style: "primary" (default, accent fill), "secondary" (outlined), or "tertiary" (text only).

func ChartTitle

func ChartTitle(t string) Option

func ClearOnSubmit added in v0.1.1

func ClearOnSubmit() Option

ClearOnSubmit resets a Form's inputs after a successful submit (st.form clear_on_submit). The submit handler still sees the submitted values; the inputs reset to type defaults (text→"", number→0, bool→false, select→first option). Widgets given an explicit DefaultValue reset to the type default, not that custom value.

func ColConfig

func ColConfig(configs map[string]ColumnConfig) Option

ColConfig is an Option that sets column configurations for DataEditor.

func Color

func Color(c string) Option

func Colors added in v0.1.1

func Colors(c []string) Option

Colors overrides the chart's series color palette with the given CSS colors.

func ColumnOrder added in v0.6.0

func ColumnOrder(cols ...string) Option

ColumnOrder reorders (and filters) the displayed columns of a DataFrame / DataEditor; columns not listed are hidden.

func DefaultValue

func DefaultValue(v any) Option

func Delta

func Delta(v string) Option

func DeltaColor

func DeltaColor(v string) Option

func Disabled

func Disabled() Option

func DynamicRows

func DynamicRows() Option

func EndTime added in v0.6.0

func EndTime(seconds float64) Option

func Expanded

func Expanded() Option

func FeedbackStyle added in v0.1.1

func FeedbackStyle(s string) Option

FeedbackStyle selects the Feedback widget's rating style: "thumbs" (default, 👍/👎 → "up"/"down"), "stars" (★ → "1".."5"), or "faces" (→ "1".."5").

func Formula added in v0.7.0

func Formula() Option

Formula gives a TextInput the formula-bar look: an ƒx marker inside the box, code font, and a code-block background — visually distinct from ordinary text inputs. Implies Mono.

func Gap

func Gap(px int) Option

func Height

func Height(v int) Option

func Help

func Help(v string) Option

func Horizontal added in v0.1.1

func Horizontal() Option

Horizontal lays out a BarChart with horizontal bars (st.bar_chart horizontal).

func Icon

func Icon(v string) Option

Icon prefixes a button's label with an icon (emoji or short string).

func ImageCaption

func ImageCaption(v string) Option

func Key

func Key(k string) Option

func LabelCollapsed

func LabelCollapsed() Option

func LabelHidden

func LabelHidden() Option

func Language

func Language(v string) Option

func LineNumbers added in v0.1.1

func LineNumbers() Option

LineNumbers shows a line-number gutter on a Code block; Wrap soft-wraps long lines instead of scrolling horizontally.

func Loop added in v0.1.1

func Loop() Option

func Max

func Max(v float64) Option

func MaxChars

func MaxChars(v int) Option

func MaxDate

func MaxDate(d string) Option

func MaxSelections

func MaxSelections(n int) Option

func MimeType

func MimeType(v string) Option

func Min

func Min(v float64) Option

func MinDate

func MinDate(d string) Option

MinDate / MaxDate bound a DateInput or DateRangeInput to a "YYYY-MM-DD" range.

func Mono added in v0.7.0

func Mono() Option

Mono renders a TextInput / TextArea in the code font — for formulas, identifiers, or anything typed character-by-character.

func Muted added in v0.1.1

func Muted() Option

func Placeholder

func Placeholder(v string) Option

func RangeSelectable added in v0.7.0

func RangeSelectable() Option

RangeSelectable lets the user drag across a Line/Bar/Area chart to select an x-axis range; the chart then returns a *ChartSelection with Range true and Index..EndIndex spanning the dragged interval. Point clicks still work.

func RunEvery added in v0.1.1

func RunEvery(d time.Duration) Option

RunEvery makes a Fragment re-run automatically on the given interval, for live dashboards (st.fragment run_every). The fragment re-executes only its own function each tick, not the whole app.

func Selectable

func Selectable() Option

Selectable enables row selection on a DataFrame; the call then returns the selected row indices.

func SelectionMode added in v0.6.0

func SelectionMode(mode string) Option

SelectionMode sets what sy.Selectable() selects on a DataFrame: "multi-row" (default), "single-row", "multi-column", or "single-column". Row modes return selected row indices; column modes return selected column indices (into the headers slice). In column modes, clicking a header selects it (sorting is disabled).

func ShowTime added in v0.6.0

func ShowTime() Option

ShowTime makes a Spinner display the elapsed time next to its label.

func Stacked added in v0.1.1

func Stacked() Option

Stacked stacks the series of a BarChart or AreaChart (st.bar_chart stack).

func StartTime added in v0.6.0

func StartTime(seconds float64) Option

StartTime / EndTime clip Audio/Video playback to a range (seconds).

func Step

func Step(v float64) Option

func Subtitles added in v0.6.0

func Subtitles(vttURL string) Option

Subtitles adds a subtitle track (WebVTT URL) to a Video.

func UseContainerWidth

func UseContainerWidth() Option

UseContainerWidth makes a button span the full width of its container.

func VerticalAlignment

func VerticalAlignment(align string) Option

func Width

func Width(v int) Option

func Wrap added in v0.1.1

func Wrap() Option

func XLabels

func XLabels(l []string) Option

func Zoom added in v0.1.1

func Zoom(level int) Option

Zoom sets the initial zoom level (1–18) of a Map.

type Page

type Page struct {
	Title string
	Fn    func()
	Icon  string
}

Page represents a page definition for use with Navigation.

type PageConfigOption

type PageConfigOption func(*pageConfig)

PageConfigOption configures the page via SetPageConfig.

func BackgroundColor

func BackgroundColor(color string) PageConfigOption

BackgroundColor sets the main background color.

func ConfigIcon

func ConfigIcon(i string) PageConfigOption

ConfigIcon sets the favicon (emoji or URL).

func ConfigLogo(src string) PageConfigOption

ConfigLogo sets the sidebar logo image URL.

func ConfigMenuItems added in v0.6.0

func ConfigMenuItems(helpURL, bugURL, aboutMarkdown string) PageConfigOption

ConfigMenuItems configures the app menu (⋮ button in the top-right corner). helpURL adds a "Get help" link, bugURL a "Report a bug" link, and aboutMarkdown fills an "About" dialog. Pass "" to omit any of them; the menu only appears when at least one is set.

func InitialSidebarState added in v0.6.0

func InitialSidebarState(state string) PageConfigOption

InitialSidebarState sets whether the sidebar starts "expanded" (default) or "collapsed". A collapsed sidebar can be reopened with the floating toggle.

func PageLayout

func PageLayout(l string) PageConfigOption

PageLayout sets the content layout. "centered" (default) or "wide".

func PageTitle

func PageTitle(t string) PageConfigOption

PageTitle sets the browser tab title.

func PrimaryColor

func PrimaryColor(color string) PageConfigOption

PrimaryColor sets the accent/primary color for the theme.

func TextColor

func TextColor(color string) PageConfigOption

TextColor sets the primary text color.

type PageOption

type PageOption func(*pageEntry)

PageOption configures a page entry in the sidebar.

func PageIcon

func PageIcon(icon string) PageOption

PageIcon sets the emoji icon displayed next to the page title in the sidebar.

func PageOrder

func PageOrder(n int) PageOption

PageOrder sets an explicit sort position for this page. Lower values appear first. Pages without an explicit order use their registration sequence (which in Go is file-name-alphabetical within a package).

type RequestContext added in v0.1.1

type RequestContext struct {
	Headers map[string]string // canonical header name -> first value
	Cookies map[string]string // cookie name -> value
	Host    string            // request host (e.g. "localhost:8600")
	IP      string            // remote address (host portion)
	Locale  string            // best-effort primary language from Accept-Language
}

RequestContext exposes read-only information about the browsing context's HTTP request — the equivalent of Streamlit's st.context. Retrieve it with Context().

In production (sy.Run / a compiled app) the values reflect the browser's WebSocket upgrade request. Under `syralit dev` the supervisor proxies the socket, so Headers/Cookies/IP describe the local supervisor connection rather than the end user.

func Context added in v0.1.1

func Context() RequestContext

Context returns information about the current session's HTTP request.

type SessionStore

type SessionStore struct {
	// contains filtered or unexported fields
}

SessionStore is the non-generic session store API (SPEC §7).

func Session

func Session() *SessionStore

Session returns the current rerun's session store for untyped access.

func (*SessionStore) Get

func (s *SessionStore) Get(key string) (any, bool)

func (*SessionStore) Set

func (s *SessionStore) Set(key string, value any)

type SharedVar added in v0.2.0

type SharedVar[T any] struct {
	// contains filtered or unexported fields
}

SharedVar is a typed handle to one app-wide shared value.

func Shared added in v0.2.0

func Shared[T any](key string, def T) *SharedVar[T]

Shared returns a handle to an app-wide value shared across all sessions, seeding it with def on first use. Unlike State (per-session), a Set is visible to every connected client and pushes a live update to all of them.

online := sy.Shared("online", 0)
online.Set(online.Get() + 1) // every other browser sees the new count

func (*SharedVar[T]) Get added in v0.2.0

func (v *SharedVar[T]) Get() T

Get returns the current shared value (the zero value of T if the stored value has a different type).

func (*SharedVar[T]) Set added in v0.2.0

func (v *SharedVar[T]) Set(val T)

Set updates the shared value and pushes a live re-render to every session.

func (*SharedVar[T]) Update added in v0.2.0

func (v *SharedVar[T]) Update(fn func(T) T)

Update applies fn to the current value atomically and broadcasts the result — use it for read-modify-write (e.g. counters) without a race between sessions.

type StateValue

type StateValue[T any] struct {
	// contains filtered or unexported fields
}

func State

func State[T any](key string, def T) *StateValue[T]

State returns a typed handle to a value that persists across reruns within the current session. On first use the default is stored; later reruns see whatever was last Set.

count := sy.State("count", 0)
if sy.Button("Add") { count.Set(count.Get() + 1) }
sy.Textf("Count: %d", count.Get())

Note (deviation from SPEC §7): SPEC sketched both a `type State[T]` interface and a `sy.State(...)` constructor, which collide in Go (a package can't have a type and a func with the same name). We keep the constructor and return the concrete *StateValue[T].

func (*StateValue[T]) Clear

func (s *StateValue[T]) Clear()

func (*StateValue[T]) Get

func (s *StateValue[T]) Get() T

func (*StateValue[T]) Set

func (s *StateValue[T]) Set(v T)

type TaskHandle added in v0.2.0

type TaskHandle[T any] struct {
	// contains filtered or unexported fields
}

TaskHandle is the result of Task: a live view of a background job's state.

func Task added in v0.2.0

func Task[T any](key string, fn func() T) TaskHandle[T]

Task runs fn in the background (a goroutine) and returns a handle to its status. The job starts on first call for a given key in a session and runs exactly once; later reruns observe its progress via the returned handle. When the job finishes, the server pushes a rerun so the UI updates on its own — the page stays responsive while the work runs, which a Streamlit rerun (which blocks) cannot do.

job := sy.Task("report", func() Report { return buildReport() })
if job.Running() {
    sy.Spinner("Crunching…")
} else {
    render(job.Result())
}

func (TaskHandle[T]) Done added in v0.2.0

func (h TaskHandle[T]) Done() bool

Done reports whether the job has finished (successfully or with an error).

func (TaskHandle[T]) Err added in v0.2.0

func (h TaskHandle[T]) Err() error

Err returns the job's error (nil unless it panicked or you stored one).

func (TaskHandle[T]) Result added in v0.2.0

func (h TaskHandle[T]) Result() T

Result returns the job's result; the zero value of T until Done.

func (TaskHandle[T]) Running added in v0.2.0

func (h TaskHandle[T]) Running() bool

Running reports whether the job is still in progress.

type Theme

type Theme struct {
	Mode string // "light" | "dark" | "system"

	ThemeStyle // main-area styles (also the defaults the sidebar inherits)

	// ShowSidebarBorder toggles the border between sidebar and main area.
	// nil keeps the default (shown).
	ShowSidebarBorder *bool

	// Chart color palettes. Categorical drives the default series colors of
	// the built-in Chart.js charts; sequential/diverging are published to the
	// front end (window.__SY_THEME) for custom components and future charts.
	ChartCategoricalColors []string
	ChartSequentialColors  []string
	ChartDivergingColors   []string

	FontFaces []FontFace // custom @font-face declarations
	Sidebar   ThemeStyle // sidebar-scoped overrides (empty fields inherit)
}

Theme controls the front-end look (SPEC §17). Visual fields live in the embedded ThemeStyle (so they are addressed as Theme.Accent etc.); the same set can be overridden for the sidebar only via Theme.Sidebar.

type ThemeStyle added in v0.6.0

type ThemeStyle struct {
	Accent       string // primary/accent color, e.g. "#7C3AED"
	Radius       string // base corner radius, e.g. "12px"
	ButtonRadius string // button corner radius; defaults to Radius

	BackgroundColor          string // app background
	SecondaryBackgroundColor string // widget/code-block/sidebar surface color
	TextColor                string // main text color
	LinkColor                string // link color; defaults to Accent
	LinkUnderline            *bool  // true: always underline links; false: never; nil: underline on hover

	CodeTextColor       string // text color for code blocks / inline code
	CodeBackgroundColor string // background for code blocks / inline code

	BorderColor                    string // general element/widget border color
	DataframeBorderColor           string // table/dataframe borders; defaults to BorderColor
	DataframeHeaderBackgroundColor string // table/dataframe header background
	ShowWidgetBorder               *bool  // false: hide input widget borders; nil/true: show

	// Basic color palette. The base color is used by badges and status
	// elements, the *BackgroundColor tint by alert surfaces, the *TextColor
	// shade by text on those surfaces (each defaults sensibly when unset).
	RedColor, OrangeColor, YellowColor, BlueColor, GreenColor, VioletColor, GrayColor                                                                       string
	RedBackgroundColor, OrangeBackgroundColor, YellowBackgroundColor, BlueBackgroundColor, GreenBackgroundColor, VioletBackgroundColor, GrayBackgroundColor string
	RedTextColor, OrangeTextColor, YellowTextColor, BlueTextColor, GreenTextColor, VioletTextColor, GrayTextColor                                           string

	// Font selects the base font for all text except code. The keywords
	// "sans-serif", "serif" and "monospace" pick the built-in Source Sans 3,
	// Source Serif 4 and Source Code Pro (embedded, served locally); any
	// other value is used verbatim as a CSS font-family list. Families not
	// installed on the visitor's machine can be loaded via Theme.FontFaces.
	Font        string
	HeadingFont string // font for titles/headers/markdown headings; defaults to Font
	CodeFont    string // font for code blocks and inline code

	BaseFontSize   int // root font size in px (0 = browser default, 16)
	BaseFontWeight int // body font weight (0 = default)

	// HeadingFontSizes / HeadingFontWeights style h1..h6 in order (and the
	// matching sy.Title / sy.Header / sy.Subheader widgets). Shorter slices
	// leave the remaining levels at their defaults.
	HeadingFontSizes   []string // CSS lengths, e.g. "2rem"
	HeadingFontWeights []int

	CodeFontSize   string // CSS length for code text, e.g. "0.875rem"
	CodeFontWeight int
}

ThemeStyle is the set of visual options that exist for both the main area and (independently) the sidebar. All fields are optional; empty means "keep the built-in default".

type UploadedFile

type UploadedFile struct {
	Name string
	Size int64
	Type string
	Data []byte
}

UploadedFile holds the data from a FileUploader widget.

func FileUploader

func FileUploader(label string, opts ...Option) *UploadedFile

FileUploader renders a file upload widget and returns the uploaded file (or nil if nothing has been uploaded). The file data is sent as base64 over the WebSocket, so this is suited for files up to a few MB.

func FileUploaderMultiple added in v0.6.0

func FileUploaderMultiple(label string, opts ...Option) []*UploadedFile

FileUploaderMultiple renders a file upload widget that accepts several files at once and returns all of them (empty slice when none are uploaded yet).

Directories

Path Synopsis
cmd
syralit command
Command syralit is the Syralit development CLI.
Command syralit is the Syralit development CLI.
examples
agent-artifact command
auth-demo command
chatbot command
data-explorer command
data-studio command
Data Studio: the full upload → explore workflow in one app.
Data Studio: the full upload → explore workflow in one app.
embed-scroll command
embed-scroll demonstrates that scrollbars inside embedded content (the Component widget, which renders custom HTML in a sandboxed iframe, and same-origin IFrames) follow the Syralit light/dark theme — a thin, rounded, transparent-track scrollbar instead of the default OS one.
embed-scroll demonstrates that scrollbars inside embedded content (the Component widget, which renders custom HTML in a sandboxed iframe, and same-origin IFrames) follow the Syralit light/dark theme — a thin, rounded, transparent-track scrollbar instead of the default OS one.
form-app command
hello command
insyra-artifact command
Example: dynamic computation in Syralit with the Insyra DSL.
Example: dynamic computation in Syralit with the Insyra DSL.
insyra-charts command
insyra-charts demonstrates Insyra's native go-echarts charts inside Syralit via the opt-in eplot subpackage — interactive chart types the built-in Chart.js layer doesn't have (Sankey, gauge, funnel, word cloud, …) — plus offline mode, which inlines the echarts JavaScript so the app needs no CDN at view time (air-gapped / strict-CSP / `syralit build` single binary).
insyra-charts demonstrates Insyra's native go-echarts charts inside Syralit via the opt-in eplot subpackage — interactive chart types the built-in Chart.js layer doesn't have (Sankey, gauge, funnel, word cloud, …) — plus offline mode, which inlines the echarts JavaScript so the app needs no CDN at view time (air-gapped / strict-CSP / `syralit build` single binary).
insyra-demo command
insyra-interactive command
Click-to-filter dashboard: an Insyra DataTable drives a selectable grouped chart; clicking a bar filters the detail table and metrics to that group — the interactive-dashboard pattern enabled by chart selections + Insyra.
Click-to-filter dashboard: an Insyra DataTable drives a selectable grouped chart; clicking a bar filters the detail table and metrics to that group — the interactive-dashboard pattern enabled by chart selections + Insyra.
mega-demo command
showcase command
streamlit-parity command
Demonstrates the Streamlit-parity additions: PDF viewer, multi-file upload, collapsed initial sidebar, app menu items, MultiSelect with free entry, toast duration, and media playback clipping.
Demonstrates the Streamlit-parity additions: PDF viewer, multi-file upload, collapsed initial sidebar, app menu items, MultiSelect with free entry, toast duration, and media playback clipping.
theme-fonts command
Demonstrates font theming: built-in font keywords ("sans-serif" / "serif" / "monospace" map to the embedded Source Sans 3 / Source Serif 4 / Source Code Pro), custom fonts loaded via [[theme.font_faces]], and size/weight tuning.
Demonstrates font theming: built-in font keywords ("sans-serif" / "serif" / "monospace" map to the embedded Source Sans 3 / Source Serif 4 / Source Code Pro), custom fonts loaded via [[theme.font_faces]], and size/weight tuning.
integrations
insyra
Package syinsyra provides first-class Insyra integration for Syralit.
Package syinsyra provides first-class Insyra integration for Syralit.
insyra/eplot
Package syiplot renders Insyra's go-echarts charts (insyra/plot) inline in a Syralit app, unlocking interactive chart types Syralit's built-in Chart.js layer doesn't have — Sankey, word cloud, K-line, gauge, funnel, theme-river, box plot, radar, and more.
Package syiplot renders Insyra's go-echarts charts (insyra/plot) inline in a Syralit app, unlocking interactive chart types Syralit's built-in Chart.js layer doesn't have — Sankey, word cloud, K-line, gauge, funnel, theme-river, box plot, radar, and more.
insyra/insyradsl
Package insyradsl runs the Insyra CLI DSL from inside Syralit apps, turning dynamic .isr computations into rendered widgets and Artifact Canvas nodes.
Package insyradsl runs the Insyra CLI DSL from inside Syralit apps, turning dynamic .isr computations into rendered widgets and Artifact Canvas nodes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL