Vaadin for Python: the easy, secure web framework with thin client architecture.
No JavaScript. No exposed APIs. 50+ enterprise-grade Vaadin components.
An easy Python web framework with built-in security. Everything you need, without leaving Python.
Write your entire UI in Python. No JavaScript, no HTML templates, no CSS. Just clean, idiomatic Python code.
Enterprise-grade UI components: Grid, Forms, Charts, Login, MenuBar, TreeGrid, and many more. Battle-tested at scale.
Built-in WebSocket support for live updates. Stream data to the browser in real time with server push.
Instant feedback with --dev mode. Edit your Python code and see changes reflected immediately in the browser.
Thin client architecture means no business logic in the browser. No REST APIs to exploit, no endpoints to attack. Security built in, not bolted on.
If you know Python, you already know PyXFlow. No frontend toolchain, no webpack, no npm. Just pip install and start building.
Your code runs on the server. The browser is just a thin client.
No APIs to expose, no JS business code to ship. Secure web development by default.
No REST APIs, no GraphQL, no endpoints to exploit. The UIDL protocol is opaque to pentesters. XSS and injection are by design impossible.
All logic, validation, and data stay on the server. Nothing sensitive reaches the browser. Dificult to tamper from DevTools.
Only UI diffs travel the wire. No full-page reloads, no heavy JS bundles to download. Instant interactions over WebSocket.
Real examples, real screenshots. From hello world to full CRUD apps.
Hello World
A complete web app in Python. Text field, button, and a notification toast.
from pyxflow import Route, Menu from pyxflow.components import * @Route("hello") @Menu("Hello", icon="vaadin:hand") class HelloView(HorizontalLayout): def __init__(self): name = TextField("Your name") button = Button("Say hello", lambda e: Notification.show(f"Hello {name.value}")) self.add(name, button)
Data Grid with Lazy Loading
Sortable columns, lazy data provider, selection events. Fetches only visible rows.
@Route("grid") @Menu("Grid", icon="vaadin:table") class GridView(VerticalLayout): def __init__(self): self.grid = Grid() self.grid.add_column("name", header="Name") self.grid.add_column("email", header="Email") self.grid.add_column("role").set_sortable(True) self.grid.add_column("city").set_sortable(True) # Lazy: only fetches visible rows self.grid.set_data_provider(self.fetch) self.add(self.grid) def fetch(self, offset, limit, sorts): return people[offset:offset+limit], len(people)
Master-Detail CRUD
SplitLayout with Grid + Form. Binder handles validation and save/cancel.
from pyxflow.components import * from pyxflow.data import Binder @Route("master-detail") @Menu("Master-Detail", icon="vaadin:split-h") class MasterDetailView(Div): def __init__(self): split = SplitLayout() self.grid = Grid() self.grid.set_columns("firstName", "lastName", "email", "phone") self.grid.set_items(people) split.add_to_primary(self.grid) form = FormLayout() self.first = TextField("First Name") self.last = TextField("Last Name") form.add(self.first, self.last) self.binder = Binder(Person) self.binder.bind_instance_fields(self) split.add_to_secondary(form) self.add(split)
50+ enterprise-grade Vaadin components, all accessible from Python.
Up and running in under a minute.