indah¶
A Python UI framework for ephemeral cloud notebooks (Colab, Runpod). Reactive, single-port, no Node required.
Build an interactive UI from a single Python file and launch it straight from a Colab or Runpod cell. indah gives you zero-config, single-port startup with the async performance of a real full-stack app, and ships its frontend pre-built so there is no Node, npm, or bun anywhere at install or runtime.
import indah
from indah import Signal, computed, Column, Slider, Text, Session
a, b = Signal(2), Signal(3)
total = computed(lambda: f"a + b = {a.value + b.value}")
page = Column(
children=[
Slider(a, min=0, max=10, label="a"),
Slider(b, min=0, max=10, label="b"),
Text(total),
]
)
indah.launch(indah.create_app(session=Session(page)))
That is a complete app. Drag a slider and only the label recomputes - no
full-script rerun. launch() prints a URL and, in a notebook, embeds the app
inline in the cell.
Status: Milestone 1 components shipped
On top of the MVP (reactive core, SSE transport, streaming, custom-component
seam), it adds the full input set and layout containers, data-driven lists,
per-session state, file upload/download, and charting (server-PNG Plot plus
client-side Chart, Heatmap, an interactive Table, Stat cards, and
ImageOverlay). pip install indah, or see Quickstart.
See it in one click¶
Every demo runs in your browser - no install, no clone - and also opens in Colab, embedded right in the cell:
Open the demo gallery Browse the demos here
A streaming chatbot, a live training dashboard, an image generator, a poster generator, and interactive charts - all in a Colab notebook or as a standalone app.
What you get¶
- Reactive, not rerun. Mutate a signal and only the components that read it update
- no full-script rerun on every interaction.
- One port, no Node. The frontend ships pre-built in the wheel, so there is nothing to build at install or runtime and it starts cleanly inside a transient Colab or Runpod container.
- Notebook-native and proxy-friendly. SSE plus HTTP POST over a single port passes the network proxies of Colab and Runpod - no WebSocket and no tunnel.
- Plain Python components bound to state, with custom layouts and a custom-component seam for when you outgrow the built-in set.
Reach for indah when you want a reactive app that runs inline in Colab or Runpod today and deploys as a standalone app tomorrow, with no Node anywhere.
How it works¶
flowchart LR
subgraph Cell["Colab / Runpod cell"]
PY["Your Python app<br/>(reactive signals)"]
end
subgraph ASGI["Single ASGI app, one port"]
CORE["Reactive core<br/>signals to JSON patches"]
API["/api: SSE + POST"]
STATIC["Pre-built Svelte shell<br/>(static assets in the wheel)"]
end
Browser["Browser via platform proxy"]
PY --> CORE --> API
STATIC -- served over HTTP --> Browser
API -- SSE patches --> Browser
Browser -- POST events --> API
One port, standard HTTP plus Server-Sent Events, so it works through the network proxies of Colab and Runpod without a tunnel or a local JavaScript toolchain. You describe the UI in Python; the reactive core turns signal changes into minimal JSON patches; the pre-built shell renders the tree and applies patches by node id.
Where to go next¶
- Quickstart - install, write your first app, and launch it.
- Components - the starter set for a typical AI demo.
- Custom components - register your own without forking or a Node build.
- Protocol - the versioned JSON contract between Python and the shell.
The design docs (plan, slices, ADRs) live in the repository.