Build Web Tools with Python Only: Introducing NiceGUI
This article introduces NiceGUI, a pure‑Python web UI framework that lets developers create fully functional, visually appealing web applications without writing any HTML, CSS, or JavaScript, covering its core concepts, quick‑start example, advanced features, component library, layout system, data‑visualisation integration, multi‑page support, suitable scenarios, and a comparison with traditional web development.
NiceGUI: a Python‑only Web UI framework
NiceGUI lets Python developers create fully functional, aesthetically pleasing web applications without writing any HTML, CSS or JavaScript. It wraps the Vue.js/Quasar stack and generates the required front‑end code automatically.
Why use NiceGUI?
Low learning cost : if you know Python, almost zero extra learning.
Fast development : ideas become interactive pages in minutes.
No environment setup : no Node.js, Webpack or other front‑end toolchains required.
Prototype‑to‑product : prototypes can be deployed directly as production apps.
5‑minute starter: a temperature converter
Environment
Python 3.7+ and a single command:
# Install NiceGUI
pip install niceguiCode
Create temperature_converter.py with the following content:
from nicegui import ui
def celsius_to_fahrenheit(celsius: float) -> float:
"""Convert °C to °F"""
return (celsius * 9 / 5) + 32
def fahrenheit_to_celsius(fahrenheit: float) -> float:
"""Convert °F to °C"""
return (fahrenheit - 32) * 5 / 9
ui.label('🌡️ Temperature Converter').classes('text-2xl font-bold text-blue-600')
with ui.row().classes('w-full gap-4'):
celsius_input = ui.input(label='Celsius (°C)', placeholder='Enter value',
validation={'Enter a number': lambda v: v == '' or v.replace('.', '', 1).isdigit()}
).classes('w-48')
fahrenheit_input = ui.input(label='Fahrenheit (°F)', placeholder='Enter value',
validation={'Enter a number': lambda v: v == '' or v.replace('.', '', 1).isdigit()}
).classes('w-48')
def update_fahrenheit():
"""Update Fahrenheit when Celsius changes"""
try:
c = float(celsius_input.value) if celsius_input.value else 0
fahrenheit_input.value = f'{celsius_to_fahrenheit(c):.2f}'
except ValueError:
fahrenheit_input.value = ''
def update_celsius():
"""Update Celsius when Fahrenheit changes"""
try:
f = float(fahrenheit_input.value) if fahrenheit_input.value else 0
celsius_input.value = f'{fahrenheit_to_celsius(f):.2f}'
except ValueError:
celsius_input.value = ''
celsius_input.on('update:model-value', lambda e: update_fahrenheit())
fahrenheit_input.on('update:model-value', lambda e: update_celsius())
with ui.card().classes('mt-4 w-full'):
ui.label('💡 Usage').classes('text-lg font-semibold')
ui.label('• Type a temperature in either box')
ui.label('• The other box updates automatically')
ui.label('• Supports decimal input, rounded to two places')
ui.run(title='Temperature Converter', favicon='🌡️', reload=True)Run the script with python temperature_converter.py and open http://localhost:8080 to see the live converter.
Advanced example: real‑time character counter
The following script demonstrates data binding, dynamic styling, and notifications.
from nicegui import ui
from datetime import datetime
ui.label('📝 Real‑time Text Analyzer').classes('text-2xl font-bold text-purple-600')
text_area = ui.textarea(label='Enter text', placeholder='Start typing...', on_change=lambda e: None).classes('w-full h-40')
with ui.row().classes('w-full gap-4 mt-4'):
char_card = ui.card().classes('flex-1')
with char_card:
ui.label('Characters').classes('text-sm text-gray-500')
char_count = ui.label('0').classes('text-3xl font-bold text-green-600')
word_card = ui.card().classes('flex-1')
with word_card:
ui.label('Words').classes('text-sm text-gray-500')
word_count = ui.label('0').classes('text-3xl font-bold text-blue-600')
line_card = ui.card().classes('flex-1')
with line_card:
ui.label('Lines').classes('text-sm text-gray-500')
line_count = ui.label('0').classes('text-3xl font-bold text-red-600')
update_time = ui.label('Last update: never').classes('text-sm text-gray-400 mt-2')
def analyze_text(e):
txt = e.args if e.args else ''
chars = len(txt)
words = len(txt.split()) if txt.strip() else 0
lines = txt.count('
') + (1 if txt else 0)
char_count.set_text(str(chars))
word_count.set_text(str(words))
line_count.set_text(str(lines))
update_time.set_text(f'Last update: {datetime.now().strftime("%H:%M:%S")}')
if chars > 200:
char_count.classes(replace='text-3xl font-bold text-red-600')
ui.notify('Text is long, consider splitting.', type='warning')
elif chars > 100:
char_count.classes(replace='text-3xl font-bold text-yellow-600')
else:
char_count.classes(replace='text-3xl font-bold text-green-600')
text_area.on('update:model-value', analyze_text)
def reset_text():
text_area.value = ''
analyze_text(type('Event', (), {'args': ''})())
ui.button('Clear text', on_click=reset_text, icon='delete').classes('mt-4')
ui.run(title='Text Analyzer', port=8081)Core advantages and practical tips
Rich built‑in components
NiceGUI provides ready‑made widgets such as ui.button, ui.checkbox, ui.select, ui.slider, ui.toggle, and ui.upload.
Powerful layout system
Vertical columns, horizontal rows, and grid layouts can be created with ui.column(), ui.row(), and ui.grid(), allowing flexible UI composition.
Data‑visualisation integration
Matplotlib figures can be embedded directly via ui.pyplot(fig).
Multi‑page applications
Define pages with the @ui.page('/') decorator and navigate between them using ui.open().
Suitable scenarios
Internal tools – data query interfaces, report generators, configuration panels.
Rapid prototyping – validate product ideas before investing in front‑end development.
Data‑science dashboards – showcase machine‑learning models and analytics.
IoT control panels – smart‑home or device monitoring interfaces.
Education and demos – algorithm visualisation and interactive teaching aids.
When a traditional stack may be preferable
Complex consumer‑facing applications requiring sophisticated front‑end interactions.
Public websites with strict SEO requirements.
Projects that need a deeply customised UI design system.
NiceGUI vs traditional web development
Implementing the same functionality with raw HTML/CSS/JS typically involves setting up a Node.js toolchain, writing separate front‑end code, and handling client‑server integration manually. NiceGUI abstracts all of that, letting developers focus on business logic.
Conclusion
NiceGUI dramatically lowers the barrier to web development for Python developers, enabling rapid creation of internal tools, prototypes, and small‑to‑medium web applications. It exemplifies a broader trend toward letting developers concentrate on core logic while the framework handles repetitive front‑end boilerplate.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Data Party THU
Official platform of Tsinghua Big Data Research Center, sharing the team's latest research, teaching updates, and big data news.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
