Skip to main content

indah

PyPI version Python versions License: Apache-2.0 CI

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. It keeps Streamlit's zero-config, single-port startup, adds 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.

See it running in your browser - the full demo gallery, live, no install and no clone.

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 (chat/gallery), per-session state, file upload/download, and charting (server-PNG Plot plus client-side Chart, Heatmap, an interactive Table, Stat cards, and ImageOverlay). Install with pip install indah. Start with docs/PLAN.md for the plan and docs/SLICES.md for what is built.

Why another one

Pain indah's answer
Streamlit reruns the whole script on every interaction Reactive signals: only the affected components update (ADR-0003)
Gradio's layout and state model get awkward past a demo Plain Python components bound to state, custom layouts
Reflex needs a Node build step that breaks in transient containers Frontend ships pre-built in the wheel; zero runtime Node (ADR-0004)
Colab's proxy does not support WebSockets SSE + HTTP POST transport that passes the proxy (ADR-0002)

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.

Try it

Run the built-in demo from a clone:

git clone https://github.com/leejianrong/indah && cd indah
uv sync --extra dev
make demo            # prints a URL; binds the first free port from 8000

make demo starts the indah Studio: every component and feature running live, one small page each, with its source underneath. It also has full example dashboards (a live log, a 20,000-row table, routing, an editor, a multi-user hosted app with roles and API tokens) and a playground where you type a few lines of indah and run them. Everything updates over SSE, with no WebSocket and no Node, and only the components that depend on a changed value are patched.

Other ways to run it:

make demo-notebook   # inline in a local JupyterLab cell
make demo-docker     # the small built-in demo, in Docker on an auto-picked free port

Prefer Docker with a stable http://indah.localhost/ hostname (via a machine-wide Traefik proxy)? make demo-traefik - see docs/DEV-DOCKER.md.

Your app

An app is a tree of components bound to reactive signals. Mutate a signal and only the components that read it update - no full-script rerun:

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))
)  # prints the URL; embeds inline in Colab/Runpod

The frontend is a pre-built Svelte shell bundled in the wheel; no Node runs at install or runtime. See docs/SLICES.md for what's next.

Components

The starter set covers a typical AI demo (input, run, streamed output):

Component Use
Text a label bound to a signal, computed, or string
Button an on_click handler (sync or async def)
Slider / TextInput / Select inputs two-way bound to a signal
Image / Plot / DataFrame display a URL/bytes, a Matplotlib figure, or a table
StreamText a container that grows token by token over SSE
Column a vertical layout container

That is the starter subset. 0.2.0 also ships layout containers (Row, Grid, Card, Tabs, Sidebar, Expander), more inputs (Checkbox, Number, Radio, MultiSelect, Date), charting (Chart, Heatmap, Table, Stat, ImageOverlay), data-driven List / Chat / Gallery, and file Upload / Download. Building a dashboard that sits inside a service (live push, big tables, overlays, routing, editors)? Start with Build a dashboard. The full list is in the Components reference.

Need something the set does not cover? Register a custom component against the public JSON protocol, no framework fork and no Node build:

import indah

indah.register_component(
    "colorpicker",
    render={
        "tag": "input",
        "attrs": {"type": "color"},
        "bind": {"value": "value"},  # element value <- signal
        "on": {"input": {"event": "input", "prop": "value"}},  # UI change -> signal
    },
)

colour = indah.Signal("#ff8800")
picker = indah.custom("colorpicker", value=colour)  # two-way, like a built-in

The pre-built shell renders it from that declarative spec at runtime. The protocol is a documented, versioned public contract: see docs/protocol.md.

Examples

Every demo is live in the demo gallery (no install, no clone), opens in one click in Colab, and is a single Python file you can run as a script (ADR-0023).

Demo Live Colab Source
Streaming chatbot Open Open In Colab chatbot.py
Live training dashboard Open Open In Colab training_dashboard.py
Image generation Open Open In Colab diffusion.py
Poster generator Open Open In Colab poster.py
Image classifier Open Open In Colab upload_classify.py
Object detection Open Open In Colab object_detection.py
Hybrid charting Open Open In Colab charts.py
Stock peer analysis Open Open In Colab stocks.py
Pretty map Open Open In Colab prettymap.py
Audio analysis Open Open In Colab audio_analysis.py

Also: examples/starter_components.py (a ~20-line tour of the component set) and examples/demo.ipynb (the built-in demo inline in a notebook). The chatbot is walked through step by step in the docs: Build a chatbot.

The Colab notebooks are generated from the demo manifest by deploy/colab/make_colab.py; regenerate them after adding a demo.

Planning and design

Doc What
docs/PLAN.md Problem, solution, scope, requirements, architecture
docs/SLICES.md Vertical build increments with test plans
docs/QUESTIONS.md Decision register
docs/protocol.md The JSON UI protocol (public contract)
docs/adr/ Architecture Decision Records

Development

uv sync --extra dev
make check        # lint + fast tests (the pre-push gate)
make help         # list all targets

See AGENTS.md for repo conventions and docs/RELEASING.md for the release process.

License

Apache License 2.0.

Metadata

Release files for indah 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for indah 0.5.0
File Size Uploaded Provenance
indah-0.5.0.tar.gz 6.2 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for indah 0.5.0
File Interpreter ABI Platform
indah-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 6.7 MB

Release files / indah-0.5.0.tar.gz

Download URL indah-0.5.0.tar.gz
Size 6.2 MB
Tags Source
SHA-256 checksum
How to use checksums
e176a44adb6d8ba88a68c51ee75cd4460a11839fd090af5f49e6ed63c3adc9c6
BLAKE2b-256 checksum
How to use checksums
424e621c5bc71644eb957005b261e2e2e7b988e439c26872727fd15e0e1d628a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / indah-0.5.0-py3-none-any.whl

Download URL indah-0.5.0-py3-none-any.whl
Size 535.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
71d7657edaf139e4faf27dc3aac113de03c19f27bc62983a9f96e7ebf1d8c7a9
BLAKE2b-256 checksum
How to use checksums
99a80587915edd23d0562243e27f04f68b6931f1ecefb983929666385fc69c48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for indah 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for indah-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page