Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
NiceGUI
https://github.com/zauberzeug/nicegui
Admin
Create web-based user interfaces with Python. The nice way.
Tokens:
182,353
Snippets:
1,280
Trust Score:
8.4
License:
MIT
Update:
5 days ago
Context
Chat
Benchmark
71.67
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Run ROS2 NiceGUI example with Docker Compose Source: https://github.com/zauberzeug/nicegui/blob/main/examples/ros2/README.md Starts the ROS2 and NiceGUI example stack. Run from the examples/ros2 folder, then access the UI at http://127.0.0.1:8080. ```bash docker compose up --build ``` -------------------------------- ### Minimal NiceGUI example with button and notification Source: https://github.com/zauberzeug/nicegui/wiki/ChatGPT-Custom-Instructions Starter example for NiceGUI: imports the ui module, creates a button that triggers a notification on click, and starts the app with ui.run(). Emphasized as great for short scripts, dashboards, robotics, IoT, smart home automation, ML, and websites. ```python from nicegui import ui ui.button('Click me', on_click=lambda: ui.notify(‘clicked’)) ui.run() ``` -------------------------------- ### Run Device Control Example Source: https://github.com/zauberzeug/nicegui/blob/main/examples/device_control/README.md Command to run the device control example. After starting, turn on the lightbulb to see autonomous heartbeat logging every 10 seconds. ```bash python main.py ``` -------------------------------- ### Start NiceGUI container with docker compose up Source: https://github.com/zauberzeug/nicegui/blob/main/examples/docker_image/README.md Starts the NiceGUI Docker container as defined in the docker-compose.yml file. Run this after adjusting the uid/gid in the compose file to match your local user. ```bash docker compose up ``` -------------------------------- ### Install uv package manager Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Install the uv package manager, which is required for the local development setup (Option 2). ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### Format and lint with pre-commit Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Run all pre-commit hooks from the project root. Hooks are installed by `uv sync`; if they aren't, run `uv run pre-commit install` once. If it fails with `RuntimeError: failed to find interpreter for Builtin discover of python_spec='python3.10'`, install Python 3.10 and ensure it's in your PATH. ```bash uv run pre-commit run --all-files ``` -------------------------------- ### Start development container with docker.sh Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Start the development container using the provided Docker script. The development server listens on http://localhost:80/ by default. ```bash ./docker.sh up app ``` -------------------------------- ### Run the NiceGUI app Source: https://github.com/zauberzeug/nicegui/blob/main/examples/node_module_integration/README.md Run this command to start the NiceGUI app as usual. ```bash python3 main.py ``` -------------------------------- ### Install NiceGUI with pip Source: https://github.com/zauberzeug/nicegui/blob/main/README.md Install the NiceGUI package using pip. This is the recommended installation method for Python 3. ```bash python3 -m pip install nicegui ``` -------------------------------- ### Run the NiceGUI server Source: https://github.com/zauberzeug/nicegui/blob/main/examples/zeromq/README.md Starts the NiceGUI server (main.py), which creates a plot and updates it with data from the ZeroMQ socket. ```bash python main.py ``` -------------------------------- ### Starting NiceGUI and ROS2 node Source: https://github.com/zauberzeug/nicegui/wiki/ROS2-turtlesim-joystick Starts the ROS2 node in a separate thread and runs the NiceGUI app. ```python app.on_startup(lambda: threading.Thread(target=ros_main).start()) # We add reload dirs to watch changes in our package ui.run(title='Turtlesim Joystick',uvicorn_reload_dirs=str(Path(__file__).parent.resolve())) ``` -------------------------------- ### app.on_startup Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Registers an async function to be called when the application starts up. ```APIDOC ## app.on_startup ### Description Registers an async function to be called when the application starts up. ### Method app.on_startup ### Parameters - **async_function** (callable) - Required - An async function to be called on startup. ### Example ```python from nicegui import app @app.on_startup async def startup(): print('App starting') ``` ``` -------------------------------- ### Install development version with pip Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Install the development version of NiceGUI directly from the main branch on GitHub to beta-test new features and catch regressions before they are released. ```bash pip install -U git+https://github.com/zauberzeug/nicegui.git@main ``` -------------------------------- ### Create a basic NiceGUI app in main.py Source: https://github.com/zauberzeug/nicegui/blob/main/README.md Create a minimal NiceGUI application in a file named main.py. It displays a label and a button that shows a notification when clicked, then starts the GUI server with ui.run(). ```python from nicegui import ui ui.label('Hello NiceGUI!') ui.button('BUTTON', on_click=lambda: ui.notify('button was pressed')) ui.run() ``` -------------------------------- ### Sync dependencies with uv Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Install NiceGUI in editable mode with all dependencies using uv, so code changes are reflected immediately. ```bash uv sync ``` -------------------------------- ### Setup the API client Source: https://github.com/zauberzeug/nicegui/wiki/Search-as-You-Type Creates an async HTTP client using httpx for making requests to the cocktail database. Async is crucial to avoid laggy interaction. ```python api = httpx.AsyncClient() ``` -------------------------------- ### Start ROS2 node with NiceGUI on_startup Source: https://github.com/zauberzeug/nicegui/wiki/ROS2-image-display Starts the ROS2 node in a separate thread when NiceGUI starts, using app.on_startup. The ui.run call configures the NiceGUI app with a title and reload directories. Running the node in a separate thread prevents blocking, and the node restarts on NiceGUI reload. ```Python app.on_startup(lambda: threading.Thread(target=ros_main).start()) # We add reload dirs to watch changes in our package ui.run(title='Image Display with NiceGUI', uvicorn_reload_dirs=str(Path(__file__).parent.resolve())) ``` -------------------------------- ### Install NPM dependencies Source: https://github.com/zauberzeug/nicegui/blob/main/examples/node_module_integration/README.md Run this command to install all third-party node modules, including is-odd and is-number, along with dev dependencies. Requires NPM to be installed. ```bash npm install ``` -------------------------------- ### Refreshable UI Example Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to use @ui.refreshable to create a UI section that can be rebuilt on demand, with a button to add items and refresh the list. ```python items = ['Apple', 'Banana'] @ui.refreshable def item_list(): for item in items: ui.label(item) item_list() # initial render def add_item(): items.append('Cherry') item_list.refresh() # clears and rebuilds ui.button('Add', on_click=add_item) ``` -------------------------------- ### Dockerfile for NiceGUI app Source: https://github.com/zauberzeug/nicegui/wiki/fly.io-Deployment Uses the zauberzeug/nicegui:1.3.13 image and installs the quotes package. Pinning a concrete version avoids conflicts when deploying later. ```dockerfile FROM zauberzeug/nicegui:1.3.13 RUN pip install --no-cache-dir quotes COPY . /app ``` -------------------------------- ### Mount NiceGUI inside an existing FastAPI app Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to mount NiceGUI inside an existing FastAPI app using `ui.run_with` instead of `ui.run`. The example defines a page with `@ui.page` and then mounts it at a specified path. ```python from fastapi import FastAPI fastapi_app = FastAPI() @ui.page('/admin') def admin(): ui.label('Admin UI') ui.run_with(fastapi_app, mount_path='/gui', storage_secret='…') # `uvicorn module:fastapi_app` — NiceGUI is mounted at /gui, FastAPI routes coexist. ``` -------------------------------- ### Marking Elements for Testing and Querying Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to use .mark() to tag elements for testing with the User fixture and for querying with ElementFilter. The test example uses the User fixture to interact with marked elements. The ElementFilter example reduces global variables by filtering elements by marker. ```python # Mark elements ui.button('Submit').mark('submit-btn') ui.input('Email').mark('email-input') ui.label().mark('result-label') # In tests (User fixture): async def test_form(user: User): await user.open('/') await user.type('test@example.com', marker='email-input') await user.click('submit-btn') await user.should_see(marker='result-label') # ElementFilter in app code (for reducing global vars): from nicegui.element_filter import ElementFilter labels = ElementFilter(marker='result-label') for label in labels: label.set_text('Updated') ``` -------------------------------- ### Run joystick node directly with python3 Source: https://github.com/zauberzeug/nicegui/wiki/ROS2-turtlesim-joystick Start the NiceGUI joystick node directly with python3 in a terminal. Requires sourcing the ROS2 distribution beforehand so the environment is correctly set. The node sends a new twist command only when the joystick changes. ```bash python3 joystick.py ``` -------------------------------- ### Workaround for starting with ros2 run (Python) Source: https://github.com/zauberzeug/nicegui/wiki/ROS2-image-display Gives control of the node to NiceGUI by overriding ui_run.APP_IMPORT_STRING. The main function is originally the ROS entry point. Consider deactivating reload because of a uvicorn bug that watches more than the set folder. ```python def main(): pass # NOTE: This is originally used as the ROS entry point, but we give the control of the node to NiceGUI. ui_run.APP_IMPORT_STRING = f'{__name__}:app' ``` -------------------------------- ### Install Chromium on Arch Linux Source: https://github.com/zauberzeug/nicegui/blob/main/tests/README.md For Arch-based Linux distributions, installs the Chromium browser (which includes the driver) via pacman. Package manager and package names may differ on other distributions. ```bash sudo pacman -S chromium ``` -------------------------------- ### Update in place vs. rebuild: show_count example Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows the bad practice of clearing and recreating elements on every data change versus the good practice of updating an existing element in place. The good approach uses label.set_text() or bind_text_from to avoid losing client-side state. ```python # BAD: destroys and recreates on every data change def show_count(): container.clear() ui.label(f'Count: {count}') # GOOD: updates the existing element in place label = ui.label('Count: 0') # then: label.set_text(f'Count: {count}') or bind_text_from ``` -------------------------------- ### app.get (FastAPI route) Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Registers a custom FastAPI GET route alongside NiceGUI. ```APIDOC ## GET /api/data ### Description Registers a custom FastAPI GET route alongside NiceGUI. ### Method GET ### Endpoint /api/data ### Response #### Success Response (200) - **value** (int) - The data value. #### Response Example ```json {"value": 42} ``` ### Example ```python from nicegui import app @app.get('/api/data') async def get_data(): return {'value': 42} ``` ``` -------------------------------- ### Write a simple NiceGUI test with Screen Source: https://github.com/zauberzeug/nicegui/blob/main/tests/README.md Basic example of using the `Screen` class in a pytest test: create a NiceGUI label, open the root URL, and verify the text appears. Uses the `screen` fixture to interact with the browser. ```py 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') ``` -------------------------------- ### ECharts, Plotly, Matplotlib, Live Line Plot, and 3D Scene examples Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to create various charts: ECharts with a bar chart, Plotly with a bar chart and a method to extend traces for live data, Matplotlib with a simple line plot, a live line plot for streaming data, and a 3D scene with a sphere and a box. ```python # ECharts (versatile, good default for most chart types) ui.echart({ 'xAxis': {'type': 'category', 'data': ['Mon', 'Tue', 'Wed']}, 'yAxis': {'type': 'value'}, 'series': [{'type': 'bar', 'data': [120, 200, 150]}], }) # From a pyecharts Chart object: # ui.echart.from_pyecharts(pyecharts_chart) # Plotly import plotly.graph_objects as go fig = go.Figure(go.Bar(x=['A', 'B'], y=[1, 2])) plot = ui.plotly(fig) # Drive plotly.js directly instead of re-sending the whole figure (efficient for live/streaming data): plot.run_plot_method('extendTraces', {'x': [[3]], 'y': [[5]]}, [0]) # append a point to trace 0 # Matplotlib / pyplot with ui.pyplot(figsize=(6, 4)) as plot: import matplotlib.pyplot as plt plt.plot([1, 2, 3], [4, 5, 6]) # Live line plot (efficient for streaming data) with ui.line_plot(n=50, update_every=5) as plot: plot.push(x_value, [y1, y2]) # 3D Scene (Three.js) with ui.scene() as scene: scene.sphere().move(x=1) scene.box().material('#ff0000') ``` -------------------------------- ### Run Vite watch process Source: https://github.com/zauberzeug/nicegui/blob/main/examples/vue_vite/README.md Starts Vite's watch mode to automatically rebuild Vue components on changes. ```bash npm run watch ``` -------------------------------- ### Binding System Example Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to bind element properties to Python object attributes or dict keys, with two-way and one-way binding, visibility binding, value transformation, and nested key binding (tuple path since v3.10). ```python class State: name = 'Alice' visible = True state = State() # Two-way binding (element ↔ object) ui.input('Name').bind_value(state, 'name') # One-way: object → element (read-only display) ui.label().bind_text_from(state, 'name') # One-way: element → object ui.input().bind_value_to(state, 'name') # Visibility binding ui.label('Hello').bind_visibility_from(state, 'visible') # With value transformation ui.label().bind_text_from(state, 'name', backward=lambda v: f'Hello, {v}!') # Bind to dict key data = {'count': 0} ui.label().bind_text_from(data, 'count', backward=str) # Bind to nested key (tuple path, since v3.10) ui.label().bind_text_from(state, ('nested', 'key')) ``` -------------------------------- ### Run blocking I/O and CPU-bound code with run.io_bound and run.cpu_bound Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Use `run.io_bound` for blocking I/O operations (e.g., requests, file access) and `run.cpu_bound` for CPU-heavy tasks. These run in thread and process pools respectively. The `run.cpu_bound` arguments and return values must be picklable, so pass module-level functions, not lambdas or closures. Both must be awaited from an async context. The process pool start method can be configured with `run.process_pool_start_method` before `ui.run()`; the default is platform-dependent but will become 'spawn' in version 4.0. If the task is cancelled or the app shuts down, these calls currently return `None` instead of raising `CancelledError` (will change in NiceGUI 4.0). ```python from nicegui import run # Blocking I/O (requests, file access, DB drivers without async support) → thread pool response = await run.io_bound(requests.get, url, timeout=3) # CPU-heavy work → process pool (arguments and return value must be picklable, # so pass module-level functions, not lambdas or closures) result = await run.cpu_bound(compute, data) # Optional: choose the multiprocessing start method for the cpu_bound pool (since 3.15). # Set it before ui.run(); None keeps the platform default, which will become 'spawn' in 4.0. run.process_pool_start_method = 'spawn' ``` -------------------------------- ### Install ChromeDriver on Windows with Chocolatey Source: https://github.com/zauberzeug/nicegui/blob/main/tests/README.md For Windows, installs ChromeDriver via Chocolatey. Assumes Chocolatey is already installed; if not, follow the instructions at https://chocolatey.org/install. ```powershell choco install chromedriver ``` -------------------------------- ### Clone and enter NiceGUI repository Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Clone your forked NiceGUI repository and navigate into the project directory to set up your local development environment. ```bash git clone https://github.com/YOUR_USERNAME/nicegui.git cd nicegui ``` -------------------------------- ### Install ChromeDriver on macOS with Homebrew Source: https://github.com/zauberzeug/nicegui/blob/main/tests/README.md For macOS, installs the ChromeDriver binary via Homebrew. Assumes Homebrew is already installed; if not, follow the instructions at https://brew.sh/. ```bash brew install --cask chromedriver ``` -------------------------------- ### Recommended project structure Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md A recommended directory layout for a NiceGUI application, separating entry point, pages, components, and models. ```text my_app/ ├── main.py # ui.run() entry point, top-level shared UI ├── pages/ │ ├── dashboard.py # @ui.page('/dashboard') def dashboard(): ... │ └── settings.py ├── components/ # Reusable @ui.refreshable functions or classes │ └── navbar.py └── models/ # Plain Python data classes / state objects └── state.py ``` -------------------------------- ### Install ChromeDriver on Debian Source: https://github.com/zauberzeug/nicegui/blob/main/tests/README.md For Debian-based Linux distributions, updates the package list and installs the Chromium driver. On Ubuntu, both `chromium-chromedriver` and `chromium-driver` resolve to a transitional stub that pulls in the Chromium snap, which is a dead end in containers, WSL, and minimal CI images; prefer Selenium Manager or install a matching ChromeDriver manually. ```bash sudo apt-get update sudo apt-get install chromium-driver ``` -------------------------------- ### ui.run_with Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Mounts NiceGUI inside an existing FastAPI app instead of using ui.run(). ```APIDOC ## ui.run_with ### Description Mounts NiceGUI inside an existing FastAPI app instead of using ui.run(). ### Method ui.run_with ### Parameters - **fastapi_app** (FastAPI) - Required - The existing FastAPI application. - **mount_path** (str) - Optional - The path to mount NiceGUI at. Default: None. - **storage_secret** (str) - Optional - Secret for app.storage.user and app.storage.browser. Default: None. ### Example ```python from fastapi import FastAPI from nicegui import ui fastapi_app = FastAPI() @ui.page('/admin') def admin(): ui.label('Admin UI') ui.run_with(fastapi_app, mount_path='/gui', storage_secret='…') ``` ``` -------------------------------- ### ui.run_with(fastapi_app, ...) Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Mounts NiceGUI inside an existing FastAPI application. ```APIDOC ## ui.run_with(fastapi_app, ...) ### Description Mounts NiceGUI inside an existing FastAPI application. ### Function Signature `ui.run_with(fastapi_app, ...)` ### Parameters - **fastapi_app** (FastAPI) - Required - The FastAPI application to mount NiceGUI into. - **...** - Additional arguments as needed. ### Usage Example ```python from fastapi import FastAPI app = FastAPI() ui.run_with(app) ``` ``` -------------------------------- ### Get uploaded file path in native mode Source: https://github.com/zauberzeug/nicegui/wiki/FAQs In native mode, use `app.native.main_window.create_file_dialog()` to get file paths from the system file picker. This is not possible with `ui.upload` due to browser security restrictions. ```python from nicegui import app, ui async def choose_file(): files = await app.native.main_window.create_file_dialog(allow_multiple=True) for file in files: ui.notify(file) ui.button('choose file', on_click=choose_file) ui.run(native=True) ``` -------------------------------- ### element.get_computed_prop Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Gets a computed Vue property from an element. ```APIDOC ## element.get_computed_prop ### Description Gets a computed Vue property from an element. ### Method Element method ### Endpoint value = await element.get_computed_prop('propName') ### Parameters #### Method Parameters - **prop_name** (string) - Required - The name of the computed property. ### Request Example ```python value = await element.get_computed_prop('propName') ``` ### Response #### Success Response Returns the value of the computed property. ``` -------------------------------- ### ui.run Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Runs the NiceGUI application with various configuration options. ```APIDOC ## ui.run ### Description Runs the NiceGUI application with various configuration options. ### Method ui.run ### Parameters - **host** (str) - Optional - The host to bind to. Default: '0.0.0.0' (or '127.0.0.1' in native mode). - **port** (int) - Optional - The port to bind to. Default: 8080 (or an open port in native mode). - **title** (str) - Optional - The page title. Default: 'NiceGUI'. - **favicon** (str) - Optional - The favicon. Can be an emoji, local image path, http(s) URL, data URL, or inline SVG. Default: None (NiceGUI icon). - **dark** (bool or None) - Optional - Whether to use dark mode. Default: False; None follows system. - **language** (str) - Optional - The language code. Default: None (Quasar element language). - **storage_secret** (str) - Optional - Secret for app.storage.user and app.storage.browser. Default: None. - **root** (callable) - Optional - Root page function. Default: None. - **viewport** (str) - Optional - The viewport meta tag. Default: 'width=device-width, initial-scale=1'. - **reload** (bool) - Optional - Auto-reload on file change (dev only). Default: True. - **show** (bool) - Optional - Whether to open the browser automatically. Default: True. - **reconnect_timeout** (float) - Optional - Grace period for a client to reconnect. Default: 3.0. - **binding_refresh_interval** (float) - Optional - Bindings pull-loop interval. Default: 0.1. - **tailwind** (bool) - Optional - Whether to enable Tailwind. Default: True. - **unocss** (str or None) - Optional - 'mini'/'wind3'/'wind4' uses UnoCSS instead of Tailwind. Default: None. - **prod_js** (bool) - Optional - Whether to use production-minified JS bundles. Default: True. - **fastapi_docs** (bool) - Optional - Whether to expose /docs, /redoc, /openapi.json. Default: False. - **endpoint_documentation** (str) - Optional - Which routes those docs list ('internal'/'page'/'all'). Default: 'none'. - **markdown** (bool) - Optional - Whether to serve pages as Markdown to agents. Default: False. - **native** (bool) - Optional - Whether to open a native window instead of a browser. Default: False. - **window_size** (tuple) - Optional - The window size. Default: None; implies native=True. - **fullscreen** (bool) - Optional - Whether to open in fullscreen. Default: False; implies native=True. - **frameless** (bool) - Optional - Whether to open frameless. Default: False; implies native=True. - **on_air** (bool or str) - Optional - True for an anonymous tunnel, or a device token string. Default: None. ### Example ```python from nicegui import ui ui.run( host='0.0.0.0', port=8080, title='My App', favicon='🚀', dark=None, language='en-US', storage_secret='my-secret', root=None, viewport='width=device-width, initial-scale=1', reload=True, show=False, reconnect_timeout=3.0, binding_refresh_interval=0.1, tailwind=True, unocss=None, prod_js=True, fastapi_docs=False, endpoint_documentation='none', markdown=False, native=False, window_size=(1024, 768), fullscreen=False, frameless=False, on_air=None, ) ``` ``` -------------------------------- ### Create NiceGUI app in main.py Source: https://github.com/zauberzeug/nicegui/wiki/Cloud-Run-Deployment Create a NiceGUI app in main.py that displays a button and shows a random greeting notification. The app runs on port 8080 with reload disabled, which is required for Cloud Run. ```python from random import choice from nicegui import ui greetings = [ "Hello!", "Hi there!", "Good morning!", "Good afternoon!", "Hey!", "Greetings!", "Howdy!", "Nice to see you!", "Lovely day, isn't it?", "Welcome!" ] ui.button('Greet', on_click=lambda: ui.notify(choice(greetings))) ui.run(reload=False, port=8080) ``` -------------------------------- ### ui.run_javascript(code) Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Executes JavaScript code in the browser. Can be awaited to get the result. ```APIDOC ## ui.run_javascript(code) ### Description Executes JavaScript code in the browser. Can be awaited to get the result. ### Function Signature `ui.run_javascript(code)` ### Parameters - **code** (string) - Required - The JavaScript code to execute. ### Usage Example ```python result = await ui.run_javascript('1 + 1') ``` ``` -------------------------------- ### Control Lightbulb Device and Subscribe to Events Source: https://github.com/zauberzeug/nicegui/blob/main/examples/device_control/README.md Shows how to instantiate a Lightbulb device, set its properties, and subscribe to its events. The device emits power_changed, brightness_changed, and log_message events, and properties are read/write accessible. ```python # 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) ``` -------------------------------- ### Create the user interface Source: https://github.com/zauberzeug/nicegui/wiki/Search-as-You-Type Creates an input field that triggers the search on change, and a row to display results. Uses Quasar props and TailwindCSS classes for styling. ```python search_field = ui.input(on_change=search).props('outlined rounded').classes('w-96') results = ui.row() ``` -------------------------------- ### Create certs directory Source: https://github.com/zauberzeug/nicegui/blob/main/examples/nginx_https/README.md Creates the 'certs/' directory required for storing the SSL certificate and key files. ```bash mkdir certs ``` -------------------------------- ### Initialize async client and running_query variable Source: https://github.com/zauberzeug/nicegui/wiki/Search-as-You-Type Initializes the HTTP client and a global variable `running_query` to track the current search task. This is the first step to cancel previous queries when typing fast. ```python api = httpx.AsyncClient() running_query: Optional[asyncio.Task] = None ``` -------------------------------- ### Run tests with pytest Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Run the test suite with pytest from the project root. Tests require python-selenium with ChromeDriver; see tests/README.md for setup. ```bash uv run pytest ``` -------------------------------- ### Run receiver script in terminal Source: https://github.com/zauberzeug/nicegui/wiki/ROS2-image-display Start the receiver Python script directly. Before running, source your ROS2 distribution to ensure the environment is correctly set. ```bash python3 receiver.py ``` -------------------------------- ### Global app object and lifecycle hooks Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to use the global `app` object to register startup/shutdown hooks, connect/disconnect handlers, exception handlers, and page deletion handlers. Also demonstrates adding custom FastAPI routes and static file serving. ```python from nicegui import app, ui # Startup / shutdown hooks app.on_startup(async_function) app.on_shutdown(async_function) app.on_connect(handler) # new client connects app.on_disconnect(handler) # client disconnects app.on_exception(handler) # unhandled exceptions (any context); per-page counterpart: ui.on_exception app.on_page_exception(handler) # unhandled exceptions raised inside a @ui.page builder app.on_delete(handler) # @ui.page client instance is being deleted (per-page teardown) # Custom FastAPI routes alongside NiceGUI @app.get('/api/data') async def get_data(): return {'value': 42} # Serve static / media files via NiceGUI's first-class helpers # (prefer these over app.mount(StaticFiles(...)) — they respect the URL prefix and per-request headers) app.add_static_files('/static', 'path/to/static_dir') # whole directory app.add_static_file(local_file='path/to/file.png', url_path='/icon.png') app.add_media_files('/media', 'path/to/videos') # streamable (Range-request support) app.add_media_file(local_file='path/to/clip.mp4', url_path='/clip.mp4') # Middleware (FastAPI passthrough) — standard pattern for auth, CORS, request logging from starlette.middleware.base import BaseHTTPMiddleware app.add_middleware(BaseHTTPMiddleware, dispatch=auth_dispatch) ``` -------------------------------- ### Test chart with Screen fixture Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Use the Screen fixture when JavaScript or real browser rendering is required. This example checks that a canvas element is rendered. ```python def test_chart(screen: Screen) -> None: screen.open('/') screen.should_contain('canvas') # chart rendered ``` -------------------------------- ### Run the ZeroMQ publisher in the background Source: https://github.com/zauberzeug/nicegui/blob/main/examples/zeromq/README.md Executes the publisher script (zmq-server.py) in the background, which sends random data to a ZeroMQ socket. Requires the zmq library to be installed. ```bash python zmq-server.py & ``` -------------------------------- ### Download Link: Use ui.button with tag=a instead of raw HTML Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Avoid raw HTML for styled download links. Use ui.button with tag=a to render an <a> element with full Quasar styling. ```python # BAD: raw HTML for a styled download link ui.html('<a href="/download" style="color: white; background: green; padding: 8px">Download</a>') # GOOD: ui.button with tag=a renders as an <a> element with full Quasar styling ui.button('Download', icon='download') \ .props('href=/download tag=a unelevated color=primary') ``` -------------------------------- ### Using layout elements as context managers Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md All layout elements are used as context managers, automatically placing children inside them. This example shows rows, columns, cards, grids, expansions, scroll areas, and splitters. ```python with ui.row(): # horizontal flex row (wrapping by default) ui.button('A') ui.button('B') with ui.column(): # vertical flex column ui.label('Top') ui.label('Bottom') with ui.card(): # Quasar QCard with shadow with ui.card_section(): ui.label('Title') with ui.grid(columns=3): # CSS grid for i in range(9): ui.label(str(i)) with ui.row().classes('w-full justify-between items-center'): ui.label('Left') ui.label('Right') with ui.expansion('Details', icon='info'): ui.label('Hidden content') with ui.scroll_area().classes('h-64'): for i in range(50): ui.label(f'Row {i}') with ui.splitter() as splitter: with splitter.before: ui.label('Left pane') with splitter.after: ui.label('Right pane') ``` -------------------------------- ### Deploy with NGINX site configuration Source: https://github.com/zauberzeug/nicegui/blob/main/examples/nginx_https/README.md Copies the nginx_site.conf to the NGINX sites-available directory, customizes it for your domain, enables the site, and reloads NGINX. This is for production deployment with your own domain and proper SSL certificate. ```bash 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 nginx ``` -------------------------------- ### app.add_static_files Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Serves a whole directory of static files via NiceGUI's first-class helper. ```APIDOC ## app.add_static_files ### Description Serves a whole directory of static files via NiceGUI's first-class helper. ### Method app.add_static_files ### Parameters - **url_path** (str) - Required - The URL path to serve the files at. - **local_directory** (str) - Required - The local directory path to serve. ### Example ```python from nicegui import app app.add_static_files('/static', 'path/to/static_dir') ``` ``` -------------------------------- ### app.on_connect Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Registers a handler to be called when a new client connects. ```APIDOC ## app.on_connect ### Description Registers a handler to be called when a new client connects. ### Method app.on_connect ### Parameters - **handler** (callable) - Required - A handler function to be called on client connection. ### Example ```python from nicegui import app @app.on_connect def on_connect(): print('Client connected') ``` ``` -------------------------------- ### AI co-authorship commit trailers Source: https://github.com/zauberzeug/nicegui/blob/main/CONTRIBUTING.md Example commit message trailers to add when using AI assistants. Some agents add them automatically; others don't, and some silently remove existing ones when amending or rebasing. Add the appropriate line if missing. ```text Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: opencode <noreply@opencode.ai> ``` -------------------------------- ### Configuration: Use own env variable for port Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Avoid using NICEGUI_* environment variables for host/port configuration as they are internal and overwritten by ui.run(). Use your own variable and pass it explicitly. ```python # BAD: configuring host/port via NICEGUI_* environment variables — they are internal to NiceGUI, # ui.run() overwrites them and (since 3.17) logs a warning; the app serves on port= (default 8080) os.environ['NICEGUI_PORT'] = '8113' # or: NICEGUI_PORT=8113 python main.py # GOOD: read your own variable and pass it explicitly ui.run(port=int(os.environ.get('PORT', 8080))) ``` -------------------------------- ### Late binding in for-loop with lambda Source: https://github.com/zauberzeug/nicegui/wiki/FAQs Demonstrates the late binding issue where a lambda captures the loop variable by reference, causing all callbacks to use the final value. The second example uses the default argument trick `i=i` to capture the current value. ```python for i in [1, 2, 3]: ui.button(i, on_click=lambda: ui.label(i)) ``` ```python for i in [1, 2, 3]: ui.button(i, on_click=lambda i=i: ui.label(i)) ``` -------------------------------- ### app.add_static_file Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Serves a single static file via NiceGUI's first-class helper. ```APIDOC ## app.add_static_file ### Description Serves a single static file via NiceGUI's first-class helper. ### Method app.add_static_file ### Parameters - **local_file** (str) - Required - The local file path. - **url_path** (str) - Required - The URL path to serve the file at. ### Example ```python from nicegui import app app.add_static_file(local_file='path/to/file.png', url_path='/icon.png') ``` ``` -------------------------------- ### Module-level state shared across users: items example Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Demonstrates the bug of using module-level variables shared across all users, and the correct approach of using local variables inside @ui.page or app.storage.user for per-user state. The bug shows all users seeing the same data with last writer wins. ```python # BUG: all users see the same data, last writer wins items = [] @ui.page('/') def index(): ui.button('Add', on_click=lambda: items.append('x')) # shared! ui.label(str(items)) # CORRECT: per-user state in app.storage or local variables inside @ui.page @ui.page('/') def index(): items = [] # local to this page invocation = per user # or: app.storage.user['items'] for persistence across reloads ``` -------------------------------- ### ui.run flags and options Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows the `ui.run` function with all its flags and their defaults. Includes host, port, title, favicon, dark mode, language, storage_secret, root, viewport, reload, show, reconnect_timeout, binding_refresh_interval, tailwind, unocss, prod_js, fastapi_docs, endpoint_documentation, markdown, native, window_size, fullscreen, frameless, and on_air. ```python ui.run( host='0.0.0.0', # default: '0.0.0.0', or '127.0.0.1' in native mode port=8080, # default: 8080, or an open port in native mode; set it here — # NICEGUI_HOST/NICEGUI_PORT env vars are internal, ignored and warned about (since 3.17) title='My App', # default: 'NiceGUI'; can be overwritten per page favicon='🚀', # default: None (NiceGUI icon); emoji, local image path, http(s) URL, data URL or inline SVG dark=None, # default: False; None = follow system language='en-US', # default: None (Quasar element language) storage_secret='my-secret', # default: None; required for app.storage.user and app.storage.browser root=None, # default: None; root page function (since 3.0) viewport='width=device-width, initial-scale=1', # this is also the default reload=True, # default: True; auto-reload on file change (dev only) show=False, # default: True, i.e. the browser is opened automatically reconnect_timeout=3.0, # default: 3.0; grace period for a client to reconnect binding_refresh_interval=0.1, # default: 0.1; bindings pull-loop interval, raise to reduce CPU tailwind=True, # default: True; disable to drop the Tailwind runtime unocss=None, # default: None; 'mini'/'wind3'/'wind4' uses UnoCSS instead of Tailwind (since 3.7) prod_js=True, # default: True; production-minified Vue/Quasar bundles fastapi_docs=False, # default: False; True exposes /docs, /redoc, /openapi.json endpoint_documentation='none', # default: 'none'; which routes those docs list ('internal'/'page'/'all') markdown=False, # default: False; experimental: serve your own pages as Markdown to agents # (Accept: text/markdown, or recognized agent UAs); override per page via @ui.page(markdown=...) # Native desktop window (pywebview) — flagship offline mode: native=False, # default: False; True opens a native window instead of a browser window_size=(1024, 768), # default: None; implies native=True fullscreen=False, # default: False; implies native=True frameless=False, # default: False; implies native=True # Tech preview: temporary public URL without port-forwarding on_air=None, # default: None; True for an anonymous tunnel, or a device token string ) ``` -------------------------------- ### Event Handling with Constructor Callbacks and .on() Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to attach event handlers to UI elements using constructor parameters (on_click, on_change, etc.) and the .on() method for DOM/Vue events. Includes throttling, client-side JS handlers, and awaiting a one-time click event. ```python # Constructor callbacks (most common) ui.button('Click', on_click=handler) ui.input('Name', on_change=handler, on_focus=handler, on_blur=handler) ui.upload(on_upload=handler, on_rejected=handler) ui.keyboard(on_key=handler) # .on() for any DOM/Vue event ui.label('Hover me').on('mouseover', handler) ui.image(...).on('click', handler, ['offsetX', 'offsetY']) # pass specific args # Throttle high-frequency events ui.input().on('keydown', handler, throttle=0.1) # Client-side only (no server round-trip) ui.button().on('click', js_handler='() => alert("hello")') # await a one-time event btn = ui.button('Click me') await btn.clicked() ``` -------------------------------- ### Get data coordinates from ui.matplotlib click Source: https://github.com/zauberzeug/nicegui/wiki/Advanced-operations-and-techniques Extracts data coordinates from a click on a ui.matplotlib plot by inverting the axes transform. The method __get_xy converts pixel coordinates (offsetX, offsetY) to data coordinates using ax.transData.inverted().transform(). This code is from the broh5 project and may need rework to be used outside a class. ```python def __get_xy(self, x, y, ax): try: xn, yn = ax.transData.inverted().transform((x, y)) return xn, yn except Exception as e: return None, None def mouse_handler(self, e: events.MouseEventArguments): """ Show the zoomed area around the mouse-clicked location or the intensity profile across the clicked location. """ if self.image is not None and ( self.enable_profile.value or self.enable_zoom.value): x, y = self.__get_xy(e.args['offsetX'], e.args['offsetY'], self.ax) ``` -------------------------------- ### Storage scopes: user, general, client, tab, and browser Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to use different storage scopes. Requires ui.run(storage_secret='...') for user and browser storage. User storage is per-user and persistent, general is global, client is per-connection in-memory, tab is per-browser-tab, and browser is read-only session data. ```python from nicegui import app # Per-user persistent storage (survives page reload, browser-session scoped) app.storage.user['username'] = 'Alice' name = app.storage.user.get('username', 'Guest') # Global shared storage (all users, persistent) app.storage.general['visit_count'] = app.storage.general.get('visit_count', 0) + 1 # Per-connection in-memory (lost on page reload) app.storage.client['temp'] = 'value' # Per-browser-tab in-memory app.storage.tab['step'] = 2 # Read-only browser session data session_id = app.storage.browser.get('id') ``` -------------------------------- ### Styling: Use ui.query instead of raw JS Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Avoid raw JavaScript for styling. Use ui.query().style() for a cleaner, more maintainable approach. ```python # BAD: raw JS for styling ui.run_javascript("document.querySelector('.my-class').style.color = 'red'") # GOOD: ui.query('.my-class').style('color: red') ``` -------------------------------- ### Quasar Theme: Use color prop instead of .style() Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Avoid passing Quasar-specific values to .style(). Use the color prop to let NiceGUI handle the Quasar theme. ```python # BAD: passing Quasar-specific values to .style() ui.button().style('background-color: var(--q-primary)') # GOOD: let NiceGUI handle Quasar theme ui.button(color='primary') ``` -------------------------------- ### Import necessary libraries Source: https://github.com/zauberzeug/nicegui/wiki/Search-as-You-Type Imports asyncio, typing.Optional, httpx, and NiceGUI modules. Required for the async search functionality and UI components. ```python import asyncio from typing import Optional import httpx from nicegui import events, ui ``` -------------------------------- ### Timer usage with repeating, once, activation control, and async callback Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows how to create a repeating timer, run a callback once after a delay, control a timer with activate/deactivate/cancel, and use an async callback. The timer interval is in seconds. ```python # Repeating timer ui.timer(1.0, lambda: label.set_text(str(datetime.now()))) # Run once after delay ui.timer(5.0, callback, once=True) # Timer with activation control t = ui.timer(0.1, callback, active=False) t.activate() t.deactivate() t.cancel() # Async callback async def update(): data = await fetch_data() label.set_text(data) ui.timer(5.0, update) ``` -------------------------------- ### Fluent Interface Formatting with Backslash Continuation Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Shows the recommended style for chaining method calls in NiceGUI, using backslash continuation for readability. ```python ui.button('Click me') \ .classes('bg-green text-white') \ .props('rounded') \ .on('click', handler) ``` -------------------------------- ### ui.date Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Creates a date picker that returns an ISO string. ```APIDOC ## ui.date ### Description Creates a date picker that returns an ISO string. ### Method Constructor ### Signature ```python ui.date(value=None, on_change=None) ``` ### Parameters - **value** (str) - Optional - Initial date in ISO format (e.g., '2024-01-01'). - **on_change** (callable) - Optional - Handler called when the date changes. ### Example ```python ui.date(value='2024-01-01') ``` ``` -------------------------------- ### Avoid double execution with startup callback Source: https://github.com/zauberzeug/nicegui/wiki/FAQs Move expensive initialization into a startup callback registered with `app.on_startup(startup)`. This ensures the callback runs only once in the child process when `reload=True`. ```python def startup(): print("Some message") app.on_startup(startup) ui.label("test") ``` -------------------------------- ### Multi-Page App: main.py Source: https://github.com/zauberzeug/nicegui/blob/main/nicegui/llms.md Entry point that registers the root route and navigates to /dashboard. Imports page modules to trigger their @ui.page registration. Runs the app with storage_secret and title. ```python # main.py from nicegui import app, ui from pages import dashboard, settings # imports trigger @ui.page registration @ui.page('/') def index(): ui.navigate.to('/dashboard') ui.run(storage_secret='my-secret', title='My App') ```