Full disclosure up front
This proposal and its proof-of-concept implementation (#PR to follow) were generated with an AI assistant (Claude), working interactively with @gagelarsen. It is a proof of concept, not a finished feature. Any and all suggestions to improve, redesign, or reject it are welcome — that's the point of this issue.
The idea
At SciPy 2026, after a Shiny for Python workshop, the observation was: a Shiny app is essentially a Tethys app without the portal ceremony. Tools like Shiny, Streamlit, and Panel all offer a "one file, one command" experience:
shiny run app.py # or: streamlit run app.py / panel serve app.py
Tethys component apps are already close to this model — pure Python, reactive, no templates — but running one currently requires: generating a portal config, configuring a database, creating a pyproject.toml, pip-installing the app, and logging in.
Proposed: tethys run app.py — run a single-file component app with zero of that:
# app.py — a complete, runnable Tethys app
from tethys_sdk.components import ComponentBase
class App(ComponentBase):
name = "My Dashboard"
@App.page
def home(lib):
return lib.tethys.Display(lib.tethys.Map())
tethys run # migrates a hidden SQLite, opens the browser, no login — just the app
Why
- Onramp: "pip install tethys-platform, write one file, run it" dramatically lowers the barrier to entry vs. the current portal setup path.
- Teaching/demos/workshops: ideal for tutorials and conference demos.
- Prototyping: iterate on an app before installing it into a real portal.
- Graduation path: the same file drops verbatim into a scaffolded component app package — start with one file, graduate to a full portal app with no rewrite. (A future
tethys scaffold --from app.py could automate this.)
Design in one paragraph
Rather than building a second runtime, the POC runs the existing portal configured down ("portal-in-a-box"): the command creates an isolated TETHYS_HOME at ~/.tethys/express/<pkg>_<hash>/ containing a generated portal_config.yml (MULTIPLE_APP_MODE: False, STANDALONE_APP, ENABLE_OPEN_PORTAL: True) and a throwaway SQLite DB, registers the bare .py file under the tethysapp namespace via sys.modules (no pip install), synthesizes missing app metadata (package/name/root_url/index) from the filename, and launches the stock dev server. Everything downstream — harvester, single-app routing, ReactPy page handling — is unmodified existing machinery, which also guarantees express apps behave identically inside a real portal.
Open questions for the team
- Is "run the full portal configured down" the right architecture, or is a purpose-built minimal runtime worth the extra surgery long-term?
- Should express mode always be anonymous (
ENABLE_OPEN_PORTAL), or support an auth flag?
- Naming:
tethys run? tethys express? Something else?
- Should this eventually support classic (template-based) apps, or stay component-only?
- Is the hidden per-app state dir (
~/.tethys/express/<hash>) the right lifecycle model?
A draft PR with the working POC (CLI command, loader, tests, and two related single-app-mode bug fixes) will be linked below.
Full disclosure up front
This proposal and its proof-of-concept implementation (#PR to follow) were generated with an AI assistant (Claude), working interactively with @gagelarsen. It is a proof of concept, not a finished feature. Any and all suggestions to improve, redesign, or reject it are welcome — that's the point of this issue.
The idea
At SciPy 2026, after a Shiny for Python workshop, the observation was: a Shiny app is essentially a Tethys app without the portal ceremony. Tools like Shiny, Streamlit, and Panel all offer a "one file, one command" experience:
shiny run app.py # or: streamlit run app.py / panel serve app.pyTethys component apps are already close to this model — pure Python, reactive, no templates — but running one currently requires: generating a portal config, configuring a database, creating a
pyproject.toml, pip-installing the app, and logging in.Proposed:
tethys run app.py— run a single-file component app with zero of that:tethys run # migrates a hidden SQLite, opens the browser, no login — just the appWhy
tethys scaffold --from app.pycould automate this.)Design in one paragraph
Rather than building a second runtime, the POC runs the existing portal configured down ("portal-in-a-box"): the command creates an isolated
TETHYS_HOMEat~/.tethys/express/<pkg>_<hash>/containing a generatedportal_config.yml(MULTIPLE_APP_MODE: False,STANDALONE_APP,ENABLE_OPEN_PORTAL: True) and a throwaway SQLite DB, registers the bare.pyfile under thetethysappnamespace viasys.modules(no pip install), synthesizes missing app metadata (package/name/root_url/index) from the filename, and launches the stock dev server. Everything downstream — harvester, single-app routing, ReactPy page handling — is unmodified existing machinery, which also guarantees express apps behave identically inside a real portal.Open questions for the team
ENABLE_OPEN_PORTAL), or support an auth flag?tethys run?tethys express? Something else?~/.tethys/express/<hash>) the right lifecycle model?A draft PR with the working POC (CLI command, loader, tests, and two related single-app-mode bug fixes) will be linked below.