NiceGUI puts FastAPI, Vue and Quasar under a Python UI layer
Create web-based user interfaces with Python. The nice way.
At a glance
- What is it?
- NiceGUI is a MIT licensed Python framework that renders a browser UI while your callbacks run inside a FastAPI application served by Uvicorn. The convenience is real for dashboards, robotics panels and ML tuning tools, and the tradeoffs surface in dependency exclusion markers, a frontend build driven by Python, and a set of deployment files rather than one supported hosting path.
- Who is it for?
- NiceGUI fits dashboards, robotics panels and ML tuning tools where one Python process owns both the logic and the screen. It does not suit teams that need a documented hosting, authentication or TLS story out of the box, and the exclusion markers on fastapi and markdown2 and the security floors on starlette and others mean you inherit a resolver conversation with the project.
- Can I use it commercially?
- Yes. MIT 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 received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- zauberzeug/nicegui16,336 ★ · +112
| Repository | 2026-09-21 | 2026-11-14 |
|---|---|---|
| zauberzeug/nicegui | 16.2k | 16.3k |
112 Stars in the last 54 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Your NiceGUI page is a route inside a FastAPI application
The whole path from nothing to a served page is two commands and a file. Install the package:
python3 -m pip install niceguiWrite the app as main.py, importing ui and calling ui.run(), then launch it:
python3 main.pyWhat sits underneath is where the design decisions are. NiceGUI is built on top of FastAPI, which is itself based on the ASGI framework Starlette and the ASGI webserver Uvicorn, and pyproject.toml reflects that directly: it declares the FastAPI and AsyncIO framework classifiers and pins fastapi, starlette and uvicorn[standard] as runtime dependencies. The examples tree carries both an api_requests entry and a fastapi entry, so combining NiceGUI pages with existing endpoints is a shape the project supports rather than an accident.
The deployment files treat it that way too. docker-compose.yml builds from development.dockerfile, publishes 80:8080, and wires a Traefik router with the rule PathPrefix(`/app`) plus a stripprefix middleware, with a comment stating its purpose is to test hosting on a sub-path.
The consequence lands on security rather than layout. Because the page is a route in your ASGI application, every access control decision belongs to you. The framework supplies dialogs, notifications, shared and individual pages and per-user persistence, and none of those is an authorization layer. Mount a NiceGUI page into an application with no authentication and you have published an interactive surface with nothing in front of it.
Complaining about state handling is the reason this project exists
The origin story is a complaint about state. The maintainers say they like Streamlit but find it does too much magic when it comes to state handling, and that their own search for an alternative turned up JustPy, whose approach they liked but found too low-level HTML for daily usage. The result borrows Vue and Quasar for the frontend while keeping Python in charge of the logic.
What that buys you is a set of explicit mechanisms rather than an implied rerun model: straight-forward data binding, refreshable functions, live-cycle events, session data, and a built-in timer that can refresh data in intervals down to every 10 ms. That interval is what pulls the framework outside ordinary web apps. The named uses include tweaking or configuring a machine learning algorithm and tuning motor controllers, and the examples directory backs that up with device_control, global_worker and audio_recorder.
What it costs is that reconciliation becomes your job. When your UI binds to Python state and the browser holds a live copy, every value that can change outside an event handler needs an explicit path back to the screen. Long-lived control panels should be tested for dropped connections and hard refreshes rather than assumed.
Dependency exclusion markers are inherited the moment you install
NiceGUI's Python requirements are unusually specific, and the reason is visible in the trailing comments of pyproject.toml. The manifest pins markdown2>=2.4.7,!=2.4.11 and fastapi>=0.109.1,!=0.123.5, holds jinja2 at 3.1.6 or above and below 4, and caps Pygments below 3.0.0. Four lines carry an inline link to a Dependabot security advisory, among them starlette and python-socketio, and python-multipart is held at a floor of 0.0.31.
Those floors and exclusions are not stylistic preferences. They record the versions the maintainers consider safe, and they arrive in your resolver as soon as you depend on NiceGUI. Two consequences follow. A lockfile assembled before these bounds existed may hold a starlette, python-socketio or python-multipart that your resolver now refuses outright, so a clean machine from last month can fail to install today. And because specific versions are excluded, upgrading FastAPI or markdown2 on its own will not necessarily resolve, even though nothing you wrote ever asked for the old version.
The habit worth forming is to treat the set as a set. Upgrade NiceGUI and let it move its neighbours rather than pinning the neighbours yourself, and when resolution conflicts with another library you hold, read the excluded version before reaching for a pin of your own.
The orjson dependency is skipped entirely on 32-bit x86
One dependency carries a platform marker rather than a plain version. orjson is declared as orjson>=3.11.5 with the condition platform_machine != 'i386' and platform_machine != 'i686' following it, so on those two architectures the JSON backend is not installed at all. The marker continues past those exclusions with a further check on the Python implementation.
That is a short line with a long tail. NiceGUI classifies itself as Operating System :: OS Independent, and on any modern 64-bit machine the marker is satisfied and orjson is present, so almost nobody notices it. On 32-bit x86 the package installs without orjson.
For most teams this belongs in a support matrix rather than in a redesign. It matters when you deploy to older 32-bit containers, or when you pin images by digest for reproducibility, because the resolved dependency set inside that image genuinely differs from the one on your laptop. Checking the marker before you fix an architecture saves an afternoon of chasing an import error that only reproduces on one machine.
The browser bundle is assembled by a Python script, not by npm
The frontend ships vendored inside the wheel, and the step that produces it is not a normal JavaScript toolchain. package.json defines exactly one script, "build": "python3 extract_core_libraries.py", and the repository carries extract_core_libraries.py alongside fetch_google_fonts.py, fetch_languages.py, summarize_dependencies.py and fetch_github_stats.py. Running npm run build therefore invokes Python.
The payload behind that script is a fixed set of pinned front-end libraries: vue 3.5.22, quasar 2.18.5, socket.io 4.8.1, dompurify at 3.4.0, sass, the Tailwind CSS browser build at 4.1.13, and the UnoCSS reset and runtime at 66.6.0. An override entry forces ws to 8.20.1 or newer, which tells you the socket.io tree has a known floor sitting underneath it.
Two things follow. You cannot rebuild or patch the assets with a plain npm build, because the extraction script owns that step and it ships with the repository rather than with the installed package. And the browser side is not thin: a Vue runtime, Quasar, socket.io carrying the live connection, and two utility-CSS toolkits present at once. If you expected a pure Python install to produce a small page, that payload is the surprise. DEPENDENCIES.md is the place to look before auditing that surface.
Native mode and webserver mode ship the same element set
NiceGUI can act as a webserver reached through a browser or run in native mode as a desktop window. The entry point makes the webserver case concrete: ui.run() starts the app, it becomes available at http://localhost:8080/, and the page reloads itself when you modify the code, with no restart step in the loop.
The feature list includes capturing keyboard input for global shortcuts, a timer refreshing down to every 10 ms, file upload, and embedded audio and video. The examples directory pairs that list with device_control, ffmpeg_extract_images, image_mask_overlay and global_worker.
Choosing native mode for a machine-side panel means binding it to a local session deliberately, not treating the absence of a browser tab as an access control. On a shared or networked machine, port 8080 is the surface to think about.
Production/Stable is a package classifier, not a deployment contract
pyproject.toml declares Development Status :: 5 - Production/Stable, and the licence is MIT, with Zauberzeug GmbH listed as author. The cadence behind that label is genuine: the default branch last took a push on 2026-11-02, and the newest release is v3.19.0 from 2026-11-02, following v3.18.0 on 2026-10-07 and v3.17.1 on 2026-09-18.
What the repository offers for running this in production is a set of deployment paths rather than a supported one. The top level carries development.dockerfile, release.dockerfile, fly.dockerfile, fly-entrypoint.sh, fly.toml and deploy.py, alongside docker.sh, docker-entrypoint.sh, docker-compose.yml and test_startup.sh. One way to see the documentation site locally is a single container, docker run -p 8080:8080 zauberzeug/nicegui.
None of these files settles the questions a hosting decision turns on. The Traefik service in docker-compose.yml is there to test hosting on a sub-path, not to serve as a reference proxy, and authentication appears in the examples directory (authentication, google_oauth2, google_one_tap_auth and descope_auth) rather than in the deployment files. Read the classifier as a statement about the library, and do the production security design yourself.
Editorial conclusion
NiceGUI fits dashboards, robotics panels and ML tuning tools where one Python process owns both the logic and the screen. It does not suit teams that need a documented hosting, authentication or TLS story out of the box, and the exclusion markers on fastapi and markdown2 and the security floors on starlette and others mean you inherit a resolver conversation with the project. Check the Python version bounds, read the excluded dependency versions, and write your own route level auth before exposing anything past localhost.
Frequently asked questions
What is NiceGUI used for?
The project names micro web apps, dashboards, robotics projects and smart home solutions, plus development work such as tweaking or configuring a machine learning algorithm and tuning motor controllers. The examples directory backs that up with device_control, global_worker, audio_recorder and ffmpeg_extract_images.
What are the key differences between NiceGUI and Streamlit?
The difference the maintainers draw is about state handling rather than a feature list: they say they like Streamlit but find it does too much magic there. The alternative they found, JustPy, felt too low-level HTML, so they combined FastAPI with Starlette and Uvicorn underneath and Vue with Quasar in the browser.
Does NiceGUI use FastAPI?
Yes. NiceGUI is built on top of FastAPI, which is based on the ASGI framework Starlette and the ASGI webserver Uvicorn. pyproject.toml declares the Framework :: FastAPI classifier and pins fastapi>=0.109.1,!=0.123.5, starlette>=1.3.1 and uvicorn[standard]>=0.22.0, and the examples tree includes a fastapi entry.
how to install nicegui
Run python3 -m pip install nicegui, which requires Python >=3.10,<4 and covers 3.10 through 3.14 per the classifiers. The package is also distributed as the zauberzeug/nicegui Docker image and on conda-forge, and a demo app written in main.py is served with python3 main.py.
is nicegui production ready
The package declares Development Status :: 5 - Production/Stable, is MIT licensed, and was last pushed on 2026-11-02 with v3.19.0 released the same day. The repository ships development, release and Fly.io deployment files, and authentication is shown in examples such as authentication and google_oauth2.
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/zauberzeug-nicegui)Star history chart for your README
[](https://hysenlabs.com/projects/zauberzeug-nicegui)Was this useful?