Skip to content

ADR-0006 — Container Runtime: native config.toml + Palette.to_config_toml()

Date: 2026-05-31 Status: Accepted


Context

Streamlit Container Runtime (Snowflake Workspace) supports .streamlit/config.toml natively, unlike legacy SiS running on a warehouse.

This file unlocks two things the library could not do cleanly before:

  1. primaryColor at the React level — Streamlit applies it directly in the React component, not via CSS. The KNOWN LIMITATIONS in style.css (slider track fill, date picker selected day) existed because --primary-color injected via CSS is ignored by React. With config.toml, these limitations disappear.

  2. Fonts without base64fontFiles in config.toml allows referencing TTF/WOFF2 files bundled in the project. The base64 hack (ADR-0005) is no longer needed in Container Runtime.

Decision

Add Palette.to_config_toml(font_files=None) to core/constants.py.

This method generates the content of .streamlit/config.toml from a Palette: - [theme.light] + primaryColor - [theme.dark] + primaryColor (dark auto-computed if Palette.dark is None) - [theme] + font = "custom" + fontFiles (if font_files provided)

setup_page() is not modified. The font=None parameter already existed — it just needs to be passed explicitly in Container Runtime.

Usage

from pinky_streamlit import PALETTES

# 1. Generate config.toml once (paste into .streamlit/config.toml)
print(PALETTES.PYTHIA.to_config_toml(font_files=["static/DMSans.woff2"]))

# 2. In each page
setup_page(session, palette=PALETTES.PYTHIA, font=None)
#                                              ↑
#                          config.toml handles font + primaryColor
#                          setup_page() only injects style.css + CSS variables

Responsibility split

What config.toml handles What setup_page() still handles
primaryColor (native React) CSS variables (--primary-darker, color-mix() shades…)
Font via fontFiles Component overrides (checkbox, toggle, pills, tabs…)
Native light / dark switch style.css normalization

CSS variables and component overrides cannot be declared in config.tomlsetup_page() remains necessary even in Container Runtime.

Consequences

Positive: - KNOWN LIMITATIONS in style.css (slider, date picker) resolved natively - End of the base64 hack for new Container Runtime apps - AppFont and _load_font_css() remain for backward compat (legacy SiS, local dev) - 8 new tests in test_constants.py cover all cases

Negative: - The app must generate config.toml once and commit it — a manual step - config.toml and Palette can diverge if one is updated without the other → mitigation: to_config_toml() is the source of truth, always regenerate from the palette

Relation to ADR-0005

ADR-0005 (base64 bundled font) remains valid for: - Legacy SiS on warehouse (no config.toml support) - Local dev without config.toml

In Container Runtime, fontFiles in config.toml is the preferred method. Both modes coexist via font=DEFAULT_FONT (legacy) vs font=None (container).