Skip to content

Quickstart

Get a FluxUI app running in under 5 minutes.


Step 1 — Install

pip install fluxui

Step 2 — Write hello_world.py

Create a file called hello_world.py:

hello_world.py
import fluxui as ui

app = ui.App("Hello FluxUI")  # (1)


@app.page("/")  # (2)
def home(session):  # (3)
    count = ui.state(0)  # (4)
    name  = ui.state("World")

    async def toggle_theme(v: bool) -> None:
        await session.set_theme("dark" if v else "light")

    with ui.Column(gap="var(--s-6)"):  # (5)
        with ui.Row(justify="space-between", align="center"):
            ui.Heading("Hello, FluxUI!", level=1)
            ui.Switch("Dark mode", on_change=toggle_theme)  # (6)

        with ui.Card(title="Counter", description="Click the buttons"):
            with ui.Row(gap="var(--s-3)", align="center"):
                ui.Button(
                    "−",
                    variant="secondary",
                    on_click=lambda: count.update(lambda v: v - 1),
                )
                ui.Metric(
                    label="Count",
                    value=lambda: str(count.value),  # (7)
                )
                ui.Button("+", on_click=lambda: count.update(lambda v: v + 1))
            ui.Button("Reset", variant="ghost", on_click=lambda: count.set(0))

        with ui.Card(title="Greeting"):
            ui.TextInput(
                label="Your name",
                placeholder="Type something…",
                value=name,
                on_change=lambda v: name.set(v),
            )
            ui.Text(lambda: f"Hello, {name.value}!")  # (8)


if __name__ == "__main__":
    app.run(port=8000)
  1. ui.App(title) creates the application. The title appears in the browser tab.
  2. @app.page("/") registers the function as the handler for the / route.
  3. session is a per-connection object. Each browser tab gets its own session and its own isolated state.
  4. ui.state(0) creates a ReactiveVar. It is scoped to this function call — each session gets its own counter.
  5. ui.Column is a context manager. Components rendered inside the with block become its children.
  6. Async on_change handlers are supported natively — useful for session.set_theme() and other awaitable calls.
  7. Passing a lambda (or any callable) to value= subscribes the component to count. Only this Metric re-renders when count changes.
  8. The lambda captures name by reference, so it always reads the latest value.

Step 3 — Run

python hello_world.py

or using the CLI:

fluxui run hello_world.py

FluxUI starts a development server with hot-reload enabled. Open http://127.0.0.1:8000 in your browser.

  FluxUI 0.1.0 — dev mode
  → http://127.0.0.1:8000
  Hot-reload: watching for changes (Ctrl+C to stop)

Step 4 — Understand What Happened

WebSocket connection

When your browser opens the page, it immediately opens a WebSocket connection to the server. FluxUI sends the initial HTML render over this socket.

State and subscriptions

ui.state(0) creates a ReactiveVar. When a component's render() reads .value on a ReactiveVar, it automatically subscribes to that variable. When you click "+" and call count.update(...), FluxUI:

  1. Updates count._value
  2. Notifies all subscribed components
  3. Re-renders only those components
  4. Sends a component_update message over the WebSocket
  5. The browser surgically patches only the changed element

Session isolation

Each browser tab (WebSocket connection) gets its own session object, and ui.state() is called fresh for each session. Two people can open your app simultaneously without interfering with each other.


Next Steps