Technical Documentation: zauberzeug/nicegui
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (`README.md`)
NiceGUI
NiceGUI is an easy-to-use, Python-based UI framework, which shows up in your web browser.
You can create buttons, dialogs, Markdown, 3D scenes, plots and much more.
It is great for micro web apps, dashboards, robotics projects, smart home solutions and similar use cases.
You can also use it in development, for example when tweaking/configuring a machine learning algorithm or tuning motor controllers.
NiceGUI is available as PyPI package, Docker image and on conda-forge as well as GitHub.
Features
- browser-based graphical user interface
- implicit reload on code change
- acts as webserver (accessed by the browser) or in native mode (eg. desktop window)
- standard GUI elements like label, button, checkbox, switch, slider, input, file upload, ...
- simple grouping with rows, columns, cards and dialogs
- general-purpose HTML and Markdown elements
- powerful high-level elements to
- plot graphs and charts,
- render 3D scenes,
- get steering events via virtual joysticks
- annotate and overlay images
- interact with tables
- navigate foldable tree structures
- embed video and audio files
- built-in timer to refresh data in intervals (even every 10 ms)
- straight-forward data binding and refreshable functions to write even less code
- notifications, dialogs and menus to provide state of the art user interaction
- shared and individual web pages
- easy-to-use per-user and general persistence
- ability to add custom routes and data responses
- capture keyboard input for global shortcuts etc.
- customize look by defining primary, secondary and accent colors
- live-cycle events and session data
- runs in Jupyter Notebooks and allows Python's interactive mode
- auto-complete support for Tailwind CSS
- SVG, Base64 and emoji favicon support
- testing framework based on pytest
Installation
python3 -m pip install niceguiUsage
Write your nice GUI in a file main.py:
from nicegui import ui
ui.label('Hello NiceGUI!')
ui.button('BUTTON', on_click=lambda: ui.notify('button was pressed'))
ui.run()Launch it with:
python3 main.pyThe GUI is now available through http://localhost:8080/ in your browser.
Note: NiceGUI will automatically reload the page when you modify the code.
Documentation and Examples
The documentation is hosted at https://nicegui.io/documentation and provides plenty of live demos.
The whole content of https://nicegui.io is implemented with NiceGUI itself
and can be started locally with docker run -p 8080:8080 zauberzeug/nicegui or by executing main.py from this repository.
You may also have a look at our in-depth examples of what you can do with NiceGUI.
In our wiki we have a list of great NiceGUI projects from the community, a section with Tutorials and a growing list of FAQs.
When building NiceGUI projects with AI assistants, point them at nicegui/llms.md โ a concise reference that ships with the package (also served at https://nicegui.io/llms.txt).
Why?
We at Zauberzeug like Streamlit
but find it does too much magic when it comes to state handling.
In search for an alternative nice library to write simple graphical user interfaces in Python we discovered JustPy.
Although we liked the approach, it is too "low-level HTML" for our daily usage.
But it inspired us to use Vue and Quasar for the frontend.
We have built on top of FastAPI,
which itself is based on the ASGI framework Starlette
and the ASGI webserver Uvicorn
because of their great performance and ease of use.
Sponsors
Maintenance of this project is made possible by all the contributors and sponsors.
If you would like to support this project and have your avatar or company logo appear below, please sponsor us. ๐
Consider this low-barrier form of contribution yourself.
Your support is much appreciated.
Contributing
Thank you for your interest in contributing to NiceGUI! We are thrilled to have you on board and appreciate your efforts to make this project even better.
As a growing open-source project, we understand that it takes a community effort to achieve our goals. That's why we welcome all kinds of contributions, no matter how small or big they are. Whether it's adding new features, fixing bugs, improving documentation, or suggesting new ideas, we believe that every contribution counts and adds value to our project.
We have provided a detailed guide on how to contribute to NiceGUI in our CONTRIBUTING.md file. We encourage you to read it carefully before making any contributions to ensure that your work aligns with the project's goals and standards.
If you have any questions or need help with anything, please don't hesitate to reach out to us. We are always here to support and guide you through the contribution process.
Included Web Dependencies
See DEPENDENCIES.md for a list of web frameworks NiceGUI depends on.
Architecture
NiceGUI is a Python framework for building web UIs with a backend-first philosophy.
Key architectural decisions:
- Backend-first: All UI logic lives in Python; the framework handles web details
- Tech stack: Python/FastAPI backend, Vue/Quasar frontend, socket.io for communication
- Single worker: Uses one uvicorn worker (thanks to full async support, no multi-process synchronization needed)
- Real-time communication: WebSocket connection is established after initial page load, kept open for client-server communication
- User interactions: All UI events are sent to backend and invoke Python functions, which can then generate UI updates
- Outbox: Accumulates UI updates and sends them in batches to the client
Overview (`tests/README.md`)
Automated Tests for NiceGUI
Motivation
Testing a user interface is hard work.
But to ensure NiceGUI is working as expected it is of utmost importance.
Even if automated testing needs a lot of infrastructure and results in long execution times, we believe that it's worth the effort when compared to manual testing.
Setup
Usually you don't need to install ChromeDriver at all.
The selenium test dependency comes with a helper called Selenium Manager that downloads a matching Chrome and ChromeDriver for you the first time the tests run.
Our tests use this helper first, so on most systems installing the test dependencies is enough.
You only need to install a browser and driver by hand in two cases: on ARM machines other than Apple Silicon Macs (like a Raspberry Pi or an ARM dev container), where the helper has nothing to download, or when you'd rather use a browser that your system installed.
If you do install ChromeDriver yourself, make sure its version matches your Chrome or Chromium โ otherwise the tests won't start.
If the browser isn't picked up automatically, point the tests at it with the CHROME_BINARY_LOCATION environment variable (our dev container sets it to /usr/bin/chromium).
Mac
brew install --cask chromedriverNote: The above instructions assume that you have already installed Homebrew (a package manager for macOS) on your system.
If you haven't, you can follow the instructions on https://brew.sh/ to install it.
Windows
choco install chromedriverNote: The above instructions assume that you have already installed Chocolatey (a package manager for Windows) on your system.
If you haven't, you can follow the instructions on https://chocolatey.org/install to install it.
Linux
For Debian:
sudo apt-get update
sudo apt-get install chromium-driverOn Ubuntu, both chromium-chromedriver and chromium-driver resolve to the same transitional stub that pulls in the Chromium snap, which is a dead end in containers, WSL, and minimal CI images.
Prefer Selenium Manager (see above), or install a matching ChromeDriver manually.
For Arch-based Linux distribution:
sudo pacman -S chromiumIf you are using a different distribution, the package manager and package names may differ.
Please refer to the documentation for your distribution for more information.
Usage
Because Selenium queries are quite cumbersome and lengthy, we introduced a Screen class.
This provides a high-level interface to work with the currently displayed state of the web browser.
The workflow is as follows:
- Get the
screenfixture by providingscreen: Screenas an argument to the function. - Write your NiceGUI code inside the function.
- Use
screen.open(...)with the appropriate URL path to start querying the website. - For example, use
screen.should_contain(...)with some text as parameter to ensure that the text is shown.
Here is a very simple example:
from nicegui import ui
from nicegui.testing import Screen
def test_hello_world(screen: Screen):
ui.label('Hello, world')
screen.open('/')
screen.should_contain('Hello, world')Have a look at the existing tests for more examples.
Internally we use selenium-fixture (see conftest.py).
To access the webdriver directly you can use the screen.selenium property.
Have a look at https://selenium-python.readthedocs.io/getting-started.html for documentation of the available method calls to the webdriver.
Overview (`examples/3d_scene/README.md`)
3D Scene
Create a webGL view and load an STL mesh illuminated with a spotlight.
Overview (`examples/ai_interface/README.md`)
AI Interface
Utilize the replicate library to perform voice-to-text transcription
and generate images from prompts with Stable Diffusion.
Overview (`examples/api_requests/README.md`)
API Requests
Fetch and display random quotes from Zen Quotes API.
Overview (`examples/audio_recorder/README.md`)
Audio Recorder
Record audio, play it back or download it.
Overview (`examples/authentication/README.md`)
Authentication
Use sessions to build a login screen.
Overview (`examples/custom_binding/README.md`)
Custom Binding
Create a custom binding for a label with a bindable background color.
Overview (`examples/custom_vue_component/README.md`)
Custom Vue Component
Write and integrate a custom Vue component.
One component is implemented using JavaScript, the other using Vue's Single-File Component (SFC) syntax.
Counter Component (counter.js)
The Counter component is a simple counter that increments a value.
On change, it emits an event with the new value.
A reset method allows to reset the counter to 0.
The JavaScript code in counter.js defines the front-end logic of the component using JavaScript.
OnOff Component (on_off.vue)
The OnOff component is a simple toggle that switches between on and off.
On change, it emits an event with the new value.
A reset method is also provided to reset the toggle to off.
The Single-File Component in on_off.vue defines the front-end logic of the component using Vue 2.
In contrast to the JavaScript code in counter.js, it splits the template, script, and style into separate sections.
Overview (`examples/descope_auth/README.md`)
Descope Auth
Build a login form and user profile using Descope.
Getting Started
- Create a Descope account.
- Setup a project and configure the "Login Flow" (first step in the Getting Started Wizard).
- Instead of following the "Integrate" instructions of the Wizard, use this example.
- Provide your Descope Project ID as environment variable:
DESCOPE_PROJECT_ID=P31sAvsSKptct5u66x0P2UKpiF9h python3 main.py
Overview (`examples/device_control/README.md`)
Device Control
Demonstrate how to control an IoT device like a lightbulb.
The dashboard UI is bound to the device's properties and events, allowing real-time interaction and logging.
Key Concepts
- Events: Device emits
power_changed,brightness_changed, andlog_messageevents - Properties: Pythonic read and write access,
lightbulb.power = Trueandlightbulb.brightness = 75 - Reactive UI: UI subscribes to events and updates automatically
- Autonomous Behavior: Device logs heartbeat every 10 seconds when powered on
- Clean Separation: Device logic independent from UI code
Usage
# Create device
lightbulb = Lightbulb()
# Control via properties
lightbulb.power = True
lightbulb.brightness = 75
# Subscribe to events
lightbulb.power_changed.subscribe(handle_power_change)
lightbulb.log_message.subscribe(log.push)Running
python main.pyTurn on the lightbulb to see autonomous heartbeat logging.
Use Cases
Ideal for IoT devices, smart home controls, industrial equipment, robotics, and hardware interfaces
where you need event-driven communication between device logic and UI.
Overview (`examples/docker_image/README.md`)
Docker Image
Use the official zauberzeug/nicegui Docker image.
This README provides a walkthrough on how to utilize the NiceGUI release docker image, zauberzeug/nicegui, available on Docker Hub.
The image is configured using a docker-compose.yml file for ease of use.
You can achieve similar results using the docker run command along with its appropriate parameters.
Testing the Setup
Modify the docker-compose.yml file to reflect your local host user's uid/gid and then execute the command:
docker compose upSpecial Docker Features
Data Persistence
NiceGUI automatically generates a .nicegui directory in the application's root directory (/app within the docker container).
In this example, the local app folder is mounted to the /app location inside the container, ensuring that the .nicegui folder remains persistent across docker restarts.
You can validate this by accessing http://localhost:8080, inputting some data for storage, and then restarting the container.
Non-Root User Execution
The application within the container operates as a non-root user (similar to the configs from linuxserver.io).
Consequently, all files generated by NiceGUI (such as the .nicegui persistence) will bear the configured uid/gid.
Docker Signal Pass-Through
The docker image is designed to relay signals from Docker, such as SIGTERM, to initiate a graceful shutdown of NiceGUI.
For instance, when you stop the container (using Ctrl+C) and subsequently examine the logs using the docker compose logs command,
you should notice the initiation of the ui.shutdown method.
Storage Secret
In the example main.py we read the storage secret from a environment variable.
This can then be defined in the docker-compose.yml (or even passed on from an .env file).
Overview (`examples/download_text_as_file/README.md`)
Download Text as File
Provide in-memory data like strings as file download.
Overview (`examples/editable_ag_grid/README.md`)
Editable AG Grid
Build an editable AG Grid allowing to add, edit, and delete rows.
Overview (`examples/editable_table/README.md`)
Editable Table
Build an editable table allowing to add, edit, and delete rows.
Overview (`examples/fastapi/README.md`)
FastAPI
Illustrate the integration of NiceGUI with an existing FastAPI application.
Overview (`examples/ffmpeg_extract_images/README.md`)
FFmpeg Extract Images
Use FFmpeg to extract images from a video file.
Overview (`examples/fullcalendar/README.md`)
FullCalendar
Show an interactive calendar using the FullCalendar library.
Overview (`examples/generate_pdf/README.md`)
Generate PDF
Create an SVG preview and PDF download from input form elements.
Overview (`examples/global_worker/README.md`)
Global Worker
Demonstrate a global worker for heavy computations with progress feedback.
Overview (`examples/google_one_tap_auth/README.md`)
Google One-Tap Auth
Authenticate users via Google One-Tap.
Overview (`examples/image_mask_overlay/README.md`)
Image Mask Overlay
Overlay an image with a mask.
Overview (`examples/infinite_scroll/README.md`)
Infinite Scroll
Present an infinitely scrolling image gallery.
Overview (`examples/lightbox/README.md`)
Lightbox
Build a thumbnail gallery where each image can be clicked to enlarge.
Overview (`examples/local_file_picker/README.md`)
Local File Picker
Demonstrate a dialog for selecting files locally on the server.
Overview (`examples/menu_and_tabs/README.md`)
Menu and Tabs
Use Quasar to create foldable menu and tabs inside a header bar.
Overview (`examples/modularization/README.md`)
Modularization
Modularize your application into multiple files and reuse code.
Overview (`examples/nginx_https/README.md`)
NGINX HTTPS
Serve NiceGUI with HTTPS encryption behind NGINX.
For running the app under a subpath, have a look at https://github.com/zauberzeug/nicegui/blob/main/examples/nginx_subpath.
Try Out
Create the
certs/directory:bashmkdir certsGenerate and self-sign an SSL certificate for "localhost":
bashopenssl req -x509 -out certs/localhost.crt -keyout certs/localhost.key -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -extensions EXT -config <( printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")Run the containerized app:
bashdocker compose upTry to access http://localhost (without the "s").
You will be automatically redirected to the HTTPS version.Depending on your browser, you should typically receive a warning that the certificate authority is invalid.
This is perfectly normal as we issued and self-signed a simple certificate for demo use locally.
So proceed anyway, e.g. on Chrome, click on "Advanced" > "Proceed to localhost (unsafe)".Note the "Hello World" message from the app accessed with encrypted connection.
Deploy in production in your self-hosted NGINX
For production, you will need your own domain and a proper SSL certificate issued by a recognized Certificate Authority (CA).
You can consider the free CA Let's Encrypt provided by the Internal Security Research Group, and use their Certbox tool to generate the certificates for your own domain.If you already have an NGINX server running and want to add your NiceGUI app,
you can reuse a stripped-down version of the nginx.conf file,
nginx_site.conf.
sudo cp nginx_site.conf /etc/nginx/sites-available/my_nicegui_app.conf
sudo nano /etc/nginx/sites-available/my_nicegui_app.conf # customize your domain, certificates, port number, etc.
sudo ln -s /etc/nginx/sites-available/mynicegui_app.conf /etc/nginx/sites-enabled
sudo systemctl reload nginxOverview (`examples/nginx_subpath/README.md`)
NGINX Subpath
Serve NiceGUI on a subpath behind a reverse proxy.
Here we use Nginx.
For a Traeffic example have a look at https://github.com/zauberzeug/nicegui/blob/main/docker-compose.yml.
Try Out
Just run
docker compose upThen you can access http://localhost/nicegui.
Overview (`examples/node_module_integration/README.md`)
Node Module Integration
Use multiple third-party NPM modules as dependencies in a NiceGUI app.
The app uses the is-odd node modules to check if a number is even or odd.
We chose this package to demonstrate a very simple node module which has a dependency itself,
namely the is-number package.
Using NPM, we can easily install both packages and bundle them into a single file which can be used in the app.
The package.json file defines the is-odd dependency and some dev dependencies for bundling the node module,
the rollup.config.mjs file configures the bundling process,
the src/index.mjs file is the entry point for the node module,
and number_checker.js as well as number_checker.py define a new UI element to be used in the NiceGUI app main.py.
First, install all third-party node modules (assuming you have NPM installed):
bashnpm installThis will create a node_modules directory containing the is-odd and is-number modules as well as some dev dependencies.
Now bundle the node module:
bashnpm run buildThis will create a dist directory containing the is-odd module.
Finally, you can run the app as usual:
bashpython3 main.py
Overview (`examples/openai_assistant/README.md`)
OpenAI Assistant
Use OpenAI's Assistant API with async/await.
Overview (`examples/opencv_webcam/README.md`)
OpenCV Webcam
Use OpenCV to capture images from a webcam.
Overview (`examples/pandas_dataframe/README.md`)
Pandas DataFrame
Display an editable pandas DataFrame.
Overview (`examples/progress/README.md`)
Progress
Demonstrate a progress bar for heavy computations.
Overview (`examples/reaktiv/README.md`)
Reaktiv Order Calculator
An order calculator using reactive signals from the reaktiv library.
This example demonstrates two approaches to building a reactive order calculator:
- Using
SignalandComputedfrom the reaktiv library to create reactive values and effects. - Using NiceGUI's
binding.bindable_dataclassto create a bindable dataclass
that automatically updates the total when price, quantity, or tax rate changes.
Overview (`examples/redis_storage/README.md`)
Redis Storage
Use Redis storage to share data across multiple instances behind a reverse proxy or load balancer.
Overview (`examples/ros2/README.md`)
ROS2
Use NiceGUI as web interface for a ROS2 robot.
This example is a basic ROS2 implementation with NiceGUI.
It starts up a user interface with virtual joystick and pose visualization reachable through http://127.0.0.1:8080.
The joystick publishes twist messages which are consumed by a simple simulator node which itself publishes the new pose of a virtual mobile robot.
ROS2 and NiceGUI are fully functional in this example.
Over all it is a bit more complex than a super minimal example to allow auto-reloading of the NiceGUI ROS2 node.
Usage
Change into the examples/ros2 folder and run:
docker compose up --buildAfterwards you can access the user interface at http://127.0.0.1:8080.
If you want to run the NiceGUI node locally or in your own ROS2 project, you can simply copy the code from the ros2_ws/src/gui folder.
Overview (`examples/script_executor/README.md`)
Script Executor
Execute scripts on selection and display the output.
Overview (`examples/search_as_you_type/README.md`)
Search As You Type
Use the public API of thecocktaildb.com to search for cocktails.
Overview (`examples/signature_pad/README.md`)
Signature Pad
Build a custom element based on the third-party NPM module signature_pad.
The app uses the signature_pad node module to create a signature pad.
In package.json, the signature_pad module is listed as a dependency,
while signature_pad.js and signature_pad.py define the new UI element which can be used in main.py.
Furthermore, rollup is used to bundle and minify the signature_pad module and places the result in the dist directory.
The rollup configuration is in rollup.config.mjs.
The entry point is defined in src/index.mjs, basically just re-exporting the signature_pad module.
First, install the third-party node modules (assuming you have NPM installed):
bashnpm installThis will create a node_modules directory containing the signature_pad module.
Build the signature_pad module:
bashnpm run buildThis will create a dist directory containing the signature_pad module.
Now you can run the app as usual:
bashpython3 main.py
Overview (`examples/single_page_app/README.md`)
Single Page App
Navigate without reloading the page.
Overview (`examples/slideshow/README.md`)
Slideshow
Implement a keyboard-controlled image slideshow.
Overview (`examples/slots/README.md`)
Slots
Use scoped slots to customize Quasar elements.
Overview (`examples/sqlite_database/README.md`)
SQLite Database
Perform CRUD operations on a SQLite database with async-support through Tortoise ORM.
Overview (`examples/svg_clock/README.md`)
SVG Clock
Display an analog clock by updating an SVG with ui.timer.
Overview (`examples/table_and_slots/README.md`)
Table and Slots
Use component slots in a table.
Overview (`examples/threaded_nicegui/README.md`)
Threaded NiceGUI
Run NiceGUI in a separate thread with event-based communication.
Overview (`examples/todo_list/README.md`)
Todo List
Build a simple todo list with checkboxes and text input.
Overview (`examples/trello_cards/README.md`)
Trello Cards
Show Trello-like cards that can be dragged and dropped into columns.
Note: NiceGUI provides a built-in make_sortable() method for drag-and-drop sorting.
This example predates that API and shows how to build a custom drag-and-drop solution from scratch
using HTML5 drag events, which gives you full control over acceptance logic and visual feedback.
Overview (`examples/vue_vite/README.md`)
Custom SFC Vue Component using Vite
Build Single-File Component (SFC) Vue components with Vite in NiceGUI.
Using Vite rather than NiceGUI's vbuild based build step currently supports more features of the SFC spec.
It might be useful to see also:
custom_vue_component: an example of a custom Vue component without a build stepsignature_pad: an example with a Rollup-based build step and Javascript dependency
There are two implementations of a counter component.CounterOptions is implemented using the options API, and CounterComposition uses the composition API.
Both use TypeScript and Vue's Single-File Component (SFC) syntax.
Quick Start
The example includes pre-built components, so you can run it immediately:
python main.pyDevelopment Setup
To modify and rebuild the Vue components, install the NPM dependencies:
npm installThen run Vite's watch process in one terminal:
npm run watchAnd the NiceGUI server in another terminal:
python main.pyThis will automatically rebuild your Vue components whenever you save changes.
Alternatively, you can rebuild components manually after making changes:
npm run buildOverview (`examples/webserial/README.md`)
Webserial
Communicate with a serial device using the WebSerial API.
Overview (`examples/websockets/README.md`)
Websockets
Use the websockets library to start a websocket server.
Overview (`examples/xterm/README.md`)
Xterm
Connect a terminal emulator xterm.js to a Bash process.
Overview (`examples/zeromq/README.md`)
ZeroMQ
Build a simple ZeroMQ PUSH/PULL server and client.
This example is a basic Zeromq implementation with NiceGUI.
It shows how to stream data from a ZeroMQ socket to a NiceGUI plot.
In order to do this, the zmq Python library is used to create a publisher and a subscriber.
The main interesting aspect is that the zmq.async library is used to create a subscriber that can be used in an asyncio loop, which is necessary to run the NiceGUI server.
Running the example
There are two components to this example: the publisher and the NiceGUI server.
In addition to the normal NiceGUI dependencies, the zmq library must be installed (see requirements.txt).
Running the publisher
The publisher is a simple Python script that sends random data to a ZeroMQ socket.
To run the publisher in the background, simply execute the following command:
python zmq-server.py &Running the NiceGUI server
The NiceGUI server is a Python script that creates a plot and updates it with data from the ZeroMQ socket.
To run it, execute the following command:
python main.pyResults
Once both the publisher and GUI server are running, you will see an updating plot on the UI.
To kill zmq-server.py running in the background, execute the following command after main.py ends.
kill -9 %%--- METRICS ---
- Files Extracted: 54
- Estimated Token Budget: ~8025 tokens
- Canonical Reference: https://codewiki.google/github.com/zauberzeug/nicegui