Rio: Python-only web apps with React-style components
WebApps in pure Python. No JavaScript, HTML and CSS needed
At a glance
- What is it?
- Rio is a Python framework that builds web and desktop UIs without HTML, CSS or JavaScript. It installs from PyPI as rio-ui, and its CLI scaffolds a working app in one command.
- Who is it for?
- Adopt Rio if you are a Python developer who wants a browser UI without touching HTML, CSS or JavaScript, and you accept that the project describes itself as Beta and that the frontend is compiled with npm. Do not adopt it if you need a mature ecosystem, a documented rollback path, or a non-Python frontend team.
- 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 4 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 October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Rio replaces, and for whom
Rio targets the gap between a Python script and a browser interface. The README states the goal plainly: you "won't need a single line of HTML, CSS, or JavaScript". That is the whole pitch. If your work is data analysis, an internal tool, or a small app that needs a real UI, and you would rather not maintain a separate frontend, Rio is aimed at you.
The intended audience shows up in the PyPI classifiers, which include "Intended Audience :: Financial and Insurance Industry" and "Intended Audience :: Information Technology", alongside "Development Status :: 4 - Beta". That Beta classifier is the honest part of the metadata. Rio is not positioned as a finished platform, and the release history backs that up: 0.10.6 in November 2024, 0.11 in March 2025, and 0.12 at the end of December 2025.
It is not a general-purpose web framework in the Django or Flask sense. There is no documented ORM, no routing table in the README, and no template language. Rio is a component framework that happens to serve over HTTP.
How state and components actually connect
Rio borrows React's model and expresses it in Python classes. The README's counter example is the clearest description of the mechanism. A component subclasses rio.Component and declares typed attributes, such as clicks: int = 0. The README says Rio "will watch these for changes and automatically update the GUI". A build method returns a tree of components, and the README notes that whenever the state of the component changes, Rio calls build again and updates the GUI according to the output.
So the data flow is: an event handler mutates an attribute, the framework notices, build runs, and the returned tree is diffed against the previous one. The README does not spell out the transport between server and browser, but the dependency list is informative. FastAPI and uvicorn are direct dependencies, and uniserde appears to handle serialization. The pyproject.toml also lists narwhals, which suggests dataframe support is wired in rather than bolted on.
The frontend is not absent, it is just not your problem. The repository root contains frontend/, vite.config.mjs and tsconfig.json, and package.json declares vite, typescript and sass as devDependencies. Rio ships a TypeScript frontend that you never write; the Python side is the only surface you touch. That is a real architectural trade-off: you gain one language, and you take on a build toolchain you did not choose.
Installing rio-ui and scaffolding a first app
Rio is published on PyPI under the name rio-ui, not rio. Installing the wrong name will either fail or pull something else. The README gives the command directly:
pip install rio-uiAfter that, the package installs a command line utility. The README describes it as "a very helpful command line utility to help you out" and shows rio new as the entry point. Running it without arguments presents built-in templates to choose from.
The README gives a complete worked example based on the tic-tac-toe template. It creates a project directory, changes into it, and starts the dev server:
rio new my-project --type website --template "Tic-Tac-Toe"
cd my-project
rio runThe flags here are --type and --template, both copied from the README. What you should see is a running app; the README claims you will "have your first app up and running in seconds". If you prefer to skip the CLI, the README's counter example is a standalone script. It ends with two calls that decide where the app runs:
app = rio.App(build=ButtonClicker)
app.run_in_browser() # Or `app.run_in_window()` to run as local app!run_in_browser serves the UI in a browser tab. run_in_window opens it as a local desktop window instead. Same component tree, two delivery targets, and that duality is one of Rio's more distinctive properties. Note the Python version floor: pyproject.toml sets requires-python = ">= 3.10".
Where Rio will not fit
The Beta classifier is not decorative. Rio's own metadata places it at Development Status 4, and the release cadence is roughly two to three releases a year. That is a slow enough rhythm that you should expect to read the changelog before every upgrade rather than assume compatibility.
The larger constraint is architectural. Because Rio's frontend is compiled with Vite and Sass, anything beyond pip install can require a Node toolchain. The README documents the pip path and the rio new path; it does not document how to build the frontend from source, what Node version is required, or how to deploy without npm. If your deployment environment is a bare Python container, that gap matters and you should verify it before committing.
There is also a capability ceiling. Rio is a UI framework. The README documents no authentication, no database layer, and no background job system. If your app needs those, you are assembling them yourself around Rio, and the documentation will not guide you. For a data-heavy internal tool with a handful of users, that is fine. For a multi-tenant product with sessions and permissions, Rio is the wrong starting point.
Rio against Streamlit and Gradio
The natural comparison is with the Python UI tools people already reach for. Streamlit and Gradio both render a UI from Python, and both are far more widely used. The difference is in the programming model, not the language.
Streamlit reruns your script top to bottom on every interaction and holds state in a session object. Rio keeps a component instance alive and mutates its attributes, which is closer to how a React developer thinks. The README's counter example makes this concrete: self.clicks += 1 mutates an attribute on a persistent object, and build re-renders from it. In Streamlit, that counter lives in st.session_state and the whole script re-executes.
Gradio is narrower still. It is built around wrapping a function with inputs and outputs, which is excellent for model demos and awkward for anything with custom layout. Rio's 50-plus built-in components, including rio.Switch, rio.Button and rio.Text, are aimed at general app layout rather than a single input-output panel.
The trade is maturity for structure. Streamlit and Gradio have larger user bases and more third-party examples. Rio gives you a component model that scales past a demo, at the cost of a smaller ecosystem and a Beta label.
Maintenance, licensing and what to check before upgrading
The repository is not archived, and the last push was on 2026-08-31, which is recent enough that the codebase is clearly still being touched. That said, commits are not releases. The most recent tagged release is 0.12 from 2025-12-31, so there is a gap between ongoing work and what you can install from PyPI.
Licensing is straightforward. Rio is Apache-2.0, declared in LICENSE.txt and confirmed by the PyPI classifier "License :: OSI Approved :: Apache Software License". Apache-2.0 is permissive and includes an explicit patent grant, which matters if Rio ends up inside a commercial product. This is not legal advice; if you are shipping Rio in a regulated context, have your own counsel read the licence and the dependency tree.
Upgrade cost is the practical concern. With releases spaced months apart, the changelog.md at the repository root is the document to read before bumping the version. Neither the README nor the release notes describe a deprecation policy or a rollback procedure. Pin your version, read the changelog, and treat each minor release as something to test rather than assume.
Editorial conclusion
Adopt Rio if you are a Python developer who wants a browser UI without touching HTML, CSS or JavaScript, and you accept that the project describes itself as Beta and that the frontend is compiled with npm. Do not adopt it if you need a mature ecosystem, a documented rollback path, or a non-Python frontend team. Before committing, check the Python version constraint (>= 3.10) against your runtime, read the changelog for what 0.12 changed, and confirm the npm build step works in your deployment pipeline.
Frequently asked questions
How do I install Rio?
Rio is on PyPI under the package name rio-ui, so the command is pip install rio-ui. Note that the distribution name differs from the project name Rio.
Does Rio require Node.js or a JavaScript build step?
The README documents only the pip install and rio new workflow, so end users do not write JavaScript. However, the repository contains a frontend/ directory with vite and sass as devDependencies, so the frontend is compiled with npm somewhere in the project's own build.
Can a Rio app run as a desktop application instead of a website?
Yes. The README's example ends with app.run_in_browser() and notes that app.run_in_window() runs it as a local app instead. The same component tree serves both targets.
Which Python versions does Rio support?
The pyproject.toml sets requires-python to ">= 3.10", and the PyPI classifiers list Python 3.10 among the supported versions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rio-labs-rio)