Open-source project
rio-labs/rio avatar
rio-labs/rio

Rio: building Python web apps without writing HTML, CSS or JavaScript

WebApps in pure Python. No JavaScript, HTML and CSS needed

3,648 stars158 forksPythonApache-2.0

At a glance

What is it?
Rio is a Python-only declarative UI framework that renders components in the browser or in a native window. It is a good fit for Python developers who want a data or internal tool with a real UI and no front-end stack, and a poor fit for teams that need hand-tuned page design or full control over the DOM.
Who is it for?
Rio suits Python developers building internal tools, dashboards or data-science front ends who would otherwise reach for a template engine or a notebook. It does not suit teams that need pixel-level control of the rendered page, an existing JavaScript component library, or search-engine-visible marketing pages.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Rio removes: the Python-to-browser handoff

Most Python web work ends at the point where a browser has to be involved. You produce data, then hand it to a template engine or a JSON API, and someone else writes the markup and the interaction code. Rio collapses that boundary. The README states that you will not need a single line of HTML, CSS or JavaScript, and the framework's own description calls it a way to create websites and apps based entirely on Python. The intended user is a Python developer who wants a real interface, not a printed table: someone building an internal CRUD tool, a data-visualisation panel or a machine-learning demo where the value is in the Python logic and the UI is a delivery mechanism. The repository topics list data-analysis, data-science, data-visualization and machine-learning alongside app and gui, which matches that reading. Rio is not trying to replace a general-purpose web framework. It is trying to remove the point at which a Python developer has to stop and learn a second language to show a result.

How the component model works: state, build, re-render

Rio's model is close to React's, expressed in Python classes. A component subclasses rio.Component and declares its state as typed attributes. The README's counter example defines clicks: int = 0 and notes that Rio watches these attributes for changes and updates the GUI automatically. The build method returns the component tree, and the documentation states that whenever the state of a component changes, Rio calls build again and updates the GUI according to the output. The event path is a plain method reference: rio.Button('Click me', on_press=self._on_press) wires the button to a method that mutates self.clicks. There is no separate store, no reducer and no explicit render call. The README also claims the framework is entirely type safe, so editors can suggest attributes and flag problems at the point of writing. That claim is worth checking against your own editor setup rather than taking on faith, because how much a type checker can infer depends on how the component base class is annotated. What is clear from the example is the shape: declare state, describe the tree, mutate state in a handler, and let the framework decide what to redraw.

Getting a project running with the rio command line

Installation is a single PyPI package. The README gives pip install rio-ui, and the package name is rio-ui rather than rio, which matters if you search PyPI by the project name. From there the workflow is driven by a CLI. rio new creates a project and offers a set of built-in templates. The README's complete example is rio new my-project --type website --template "Tic-Tac-Toe", followed by cd my-project and rio run. That is the whole loop: scaffold, enter the directory, run. The same example shows the two hosting modes available to an app object. app.run_in_browser() serves the app to a browser, and app.run_in_window(), named in a comment in the same snippet, runs it as a local application window instead. The README describes dev tools as included, though it does not enumerate them in the material available here, so what those tools expose is something to check in the documentation rather than assume. The template flag is worth noting as a design choice: scaffolding is opinionated, and the starting point you pick shapes the file layout you then live with.

Fifty components, and the ceiling that comes with them

The README lists over 50 built-in components, naming rio.Switch, rio.Button and rio.Text as examples, and describes the intended composition path: pull from the built-ins, combine them into custom components, then combine those into apps. That is a normal component-framework story and it works well for the kind of interface Rio targets. The limitation is the obvious one. When the component set is the source of truth, anything outside it has to be expressed through the components that exist. A designer handing you a mockup with a specific grid, a custom chart interaction or a non-standard form control has no direct path into the renderer, because the renderer is not HTML you can edit. The README's promise of zero CSS is the same fact stated positively. For an internal dashboard this rarely bites. For a marketing page, a design-led product surface, or anything where the visual result is the deliverable rather than the data behind it, the constraint becomes the whole project. Rio's own framing, websites and apps, covers a wider range than the component list comfortably supports.

Where this approach is the wrong tool

The clearest mismatch is server-rendered, search-visible content. Rio apps run in a browser or a window, and the framework's value is in interactive component state. A documentation site, a blog or a marketing page gains nothing from a state-driven component tree and loses the straightforward crawlable markup that a template engine produces. The second mismatch is teams with an existing front-end investment. If you already have a React component library, a design system or a JavaScript build pipeline, Rio asks you to abandon all of it and rebuild in Python components, and it offers no described interoperability path in the material available. The third is any project that needs to reason about the rendered DOM directly, for accessibility auditing, custom browser extensions or third-party script integration. Those tasks assume HTML you can inspect and modify. A framework whose selling point is that you never write HTML is, by construction, not the tool for them. None of this makes Rio deficient. It makes the boundary of its usefulness fairly sharp.

Compared with Streamlit and Dash

The natural comparison is with Python UI tools that also avoid front-end code, and the difference is in what they assume about the app. Streamlit and Dash are built around a script that reruns or a callback graph that fires, with the page as a sequence of outputs. Rio is built around persistent component objects with typed attributes that Rio watches for changes, as the counter example shows. That is a different mental model: you hold state on an object and mutate it, rather than recomputing a script top to bottom or wiring callbacks to individual inputs. The second difference is the deployment surface. Rio apps can run in a browser or as a local window through run_in_window, which the README presents as a first-class option rather than a wrapper. Tools that assume a server process and a browser tab do not offer that. Neither approach is better in the abstract. If your app is a linear report, the script model is simpler. If your app has genuine component state that persists and changes, Rio's model maps to it more directly.

Maintenance, versioning and the Apache-2.0 licence

Rio is licensed under Apache-2.0, which permits commercial use, modification and redistribution provided the licence and notices are preserved, and it includes an explicit patent grant. That is a permissive licence with fewer conditions than a copyleft one, but the obligations are real: if you ship a modified version, the notice requirements apply. This is not legal advice, and if you are distributing Rio inside a product, read the licence text and your own counsel's guidance rather than this summary. On maintenance, the release history is the useful signal. The listed releases are 0.10.6 in November 2024, 0.11 in March 2025 and 0.12 in December 2025, with the last push to the repository dated August 2026. The project is not archived. The version numbers are still below 1.0, which in practice means the API can change between minor releases, and the gap between 0.11 and 0.12 is around nine months. The practical consequence is that upgrading is a deliberate act, not something to leave to an unpinned dependency. Pin rio-ui in your requirements file and read the release notes before moving a minor version. The README's closing line about Rio keeping getting better with new features is cut off mid-sentence in the material available here, so treat the feature roadmap as something to read on the project's own release page.

Editorial conclusion

Rio suits Python developers building internal tools, dashboards or data-science front ends who would otherwise reach for a template engine or a notebook. It does not suit teams that need pixel-level control of the rendered page, an existing JavaScript component library, or search-engine-visible marketing pages. Before committing, run pip install rio-ui, then rio new and rio run on one real screen from your app, and check the release cadence on PyPI: 0.10.6, 0.11 and 0.12 are roughly a year apart, so plan to pin a version rather than track the latest.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. rio-labs/rio on GitHub
Community notes

Community notes