FluxUI¶
Build beautiful, reactive Python web UIs — without writing a single line of JavaScript.
FluxUI uses WebSockets to surgically re-render only the components that changed. Define your UI in pure Python, run it like a script.
Why FluxUI?¶
WebSocket-Reactive¶
State changes push targeted HTML patches over a persistent WebSocket — no full page reload, no polling. Only the components that actually changed are re-rendered.
Zero JavaScript¶
Write your entire UI — logic, layout, and interactivity — in pure Python. No JSX, no bundlers, no node_modules.
Component Overrides¶
Replace any built-in component with your own implementation via @ui.override("Button"). Works globally or per-page.
Multi-Page SPA¶
Declare pages with @app.page("/path"). Navigation happens client-side with no full page reload. Path parameters and programmatic navigation included.
Plugin Ecosystem¶
Extend FluxUI with installable Python packages. ui.use_plugin("fluxui-charts") drops in new components and themes with a single line.
Dark Mode Built-In¶
Every component is styled with CSS custom properties. Switch themes at runtime with session.set_theme("dark") — no flash, no overhead.
See It in 15 Lines¶
import fluxui as ui
app = ui.App("Counter")
@app.page("/")
def home(session):
count = ui.state(0) # (1) reactive variable
dark = ui.state(False)
async def toggle(v):
dark.set(v)
await session.set_theme("dark" if v else "light")
with ui.Column(gap="var(--s-6)"):
with ui.Row(justify="space-between"):
ui.Heading("Counter Demo", level=1)
ui.Switch("Dark mode", checked=dark, on_change=toggle)
with ui.Card(title="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)) # (2) auto-subscribed
ui.Button("+", on_click=lambda: count.update(lambda v: v + 1))
ui.Button("Reset", variant="ghost", on_click=lambda: count.set(0))
app.run(port=8000)
ui.state(0)creates a reactive variable. Any component that reads it insiderender()will automatically re-render when it changes.- Passing a
lambdatovalue=subscribes theMetrictocount. Whencountchanges, only this metric is updated — not the whole page.
How FluxUI Compares¶
| Feature | FluxUI | Streamlit | Gradio | Panel |
|---|---|---|---|---|
| Targeted re-renders | Yes | No | No | Partial |
| Multi-page SPA | Yes | Partial | No | Yes |
| Component override | Yes | No | No | No |
| Plugin ecosystem | Yes | Limited | No | Limited |
| Dark mode | Runtime | Config only | Config only | Config only |
| File upload | Yes | Yes | Yes | Yes |
| Charts (Plotly) | Yes | Yes | Yes | Yes |
| DataGrid | Yes | No | No | Yes |
| Custom JS | Yes | Experimental | No | Yes |
| Bundle size | ~40 KB | ~3 MB | ~2 MB | ~5 MB |
Next Steps¶
- Install FluxUI —
pip install fluxui - 5-minute quickstart — write and run your first app
- Core concepts — understand the reactive model
- Component reference — all 35+ components documented
- Examples — copy-paste runnable demos