#!/usr/bin/env python3
from pathlib import Path
import docutils.core
from pygments.formatters import HtmlFormatter
from nicegui import Client, ui
from website import demo_card, reference
from website.constants import ACCENT_COLOR, HEADER_HEIGHT, STATIC
from website.example import bash_window, python_window
ui.add_static_files('/favicon', Path(__file__).parent / 'website' / 'favicon')
def add_head_html() -> None:
ui.add_head_html('')
ui.add_head_html(docutils.core.publish_parts('', writer_name='html')['stylesheet'])
ui.add_head_html(f'')
ui.add_head_html('''
''') # https://realfavicongenerator.net/
ui.add_head_html(f'''
''')
ui.add_head_html(f'''
''')
def add_header() -> None:
with ui.header() \
.classes('items-center duration-200 px-4', remove='q-pa-md') \
.style(f'box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1)'):
ui.html((STATIC / 'happy_face.svg').read_text()).classes('w-8 stroke-white')
with ui.link(target=index_page):
ui.html((STATIC / 'nicegui_word.svg').read_text()).classes('w-24')
with ui.row().classes('items-center ml-auto'):
ui.link('Features', '/#features').classes(replace='text-lg text-white')
ui.link('Installation', '/#installation').classes(replace='text-lg text-white')
ui.link('Examples', '/#examples').classes(replace='text-lg text-white')
ui.link('API Reference', reference_page).classes(replace='text-lg text-white')
with ui.link(target='https://github.com/zauberzeug/nicegui/'):
ui.html((STATIC / 'github.svg').read_text()).classes('fill-white scale-125 m-1')
@ui.page('/')
async def index_page(client: Client):
client.content.classes(remove='q-pa-md gap-4')
add_head_html()
add_header()
with ui.row() \
.classes('w-full q-pa-md items-center gap-12 no-wrap') \
.style(f'height: calc(100vh - {HEADER_HEIGHT}); transform: translateX(-250px)'):
ui.html((STATIC / 'happy_face.svg').read_text()).classes('stroke-black').style('width: 500px')
with ui.column().classes('gap-8'):
ui.html('Meet the NiceGUI.') \
.style('font-size: 400%; line-height: 0.9; font-weight: 500')
ui.markdown('Your easy-to-use Python framework to create\n\nuser interfaces which show up in the browser.') \
.style('font-size: 200%; line-height: 0.9')
with ui.row() \
.classes('w-full q-pa-md items-center gap-28 p-32 no-wrap') \
.style(f'height: calc(100vh - {HEADER_HEIGHT}); background: {ACCENT_COLOR}'):
with ui.column().classes('gap-6'):
ui.markdown('Create buttons, dialogs, markdown,\n\n3D scenes, plots and much more at ease.') \
.style('font-size: 300%; color: white; line-height: 0.9; font-weight: 500').classes('mb-4')
ui.label('''
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.
''').style('font-size: 150%; color: white').classes('leading-tight')
with ui.row().style('font-size: 150%; color: white').classes('leading-tight gap-2'):
ui.html('''
NiceGUI is available as
PyPI packagenorth_east,
Docker imagenorth_east and on
GitHubnorth_east.
''')
demo_card.create()
ui.link_target('features').style(f'position: relative; top: -{HEADER_HEIGHT}')
with ui.column().classes('w-full q-pa-xl'):
ui.label('Features').classes('text-bold text-lg')
ui.html('What has NiceGUI to offer?') \
.style('font-size: 300%; font-weight: 500; margin-top: -20px')
with ui.row().classes('w-full no-wrap text-lg leading-tight justify-between'):
with ui.column().classes('gap-1'):
ui.label('User Interface').classes('text-bold mb-4')
ui.markdown('- common elements like label, button, checkbox, switch, slider, input, ...')
ui.markdown('- page layout with navigation bars, tabs, panels, ...')
ui.markdown('- grouping with rows, columns, cards and dialogs')
ui.markdown('- HTML and markdown elements')
ui.markdown('- high-level elements like charts, tables, trees, 3D scenes, joystick, ...')
ui.markdown('- built-in timer to refresh data in intervals')
ui.markdown('- notifications, dialogs and menus')
ui.markdown('- keyboard input')
with ui.column().classes('gap-1'):
ui.label('Under the hood').classes('text-bold mb-4')
ui.markdown('- browser-based graphical user interface')
ui.markdown('- based on FastAPI and Uvicorn')
ui.markdown('- live-cycle events and session data')
ui.markdown('- customizable page layout and colors')
with ui.column().classes('gap-1'):
ui.label('Development').classes('text-bold mb-4')
ui.markdown('- implicit reload on code change')
ui.markdown('- straight-forward data binding')
ui.link_target('installation').style(f'position: relative; top: -{HEADER_HEIGHT}')
with ui.column().classes('w-full q-pa-xl'):
ui.label('Installation').classes('text-bold text-lg')
ui.html('Getting started') \
.style('font-size: 300%; font-weight: 500; margin-top: -20px')
with ui.row().classes('w-full no-wrap text-lg leading-tight'):
with ui.column().classes('w-1/3 gap-2'):
ui.html('1.').classes('text-3xl text-bold')
ui.markdown('Install').classes('text-lg')
with bash_window().classes('w-full h-52'):
ui.markdown('```bash\npython3 -m pip install nicegui\n```')
with ui.column().classes('w-1/3 gap-2'):
ui.html('2.').classes('text-3xl text-bold')
ui.markdown('Write file __main.py__').classes('text-lg')
with python_window().classes('w-full h-52'):
ui.markdown('''```python\n
from nicegui import ui
ui.label('Hello NiceGUI!')
ui.run()
```''')
with ui.column().classes('w-1/3 gap-2'):
ui.html('3.').classes('text-3xl text-bold')
ui.markdown('Launch it with').classes('text-lg')
with bash_window().classes('w-full h-52'):
ui.markdown('```bash\npython3 main.py\n```')
ui.link_target('examples').style(f'position: relative; top: -{HEADER_HEIGHT}')
with ui.column().classes('w-full q-pa-xl'):
ui.label('Documentation').classes('text-bold text-lg')
ui.html('Interactive Examples') \
.style('font-size: 300%; font-weight: 500; margin-top: -20px')
reference.create_intro()
with ui.row() \
.classes('w-full items-center gap-28 px-32 py-16 no-wrap') \
.style(f'background: {ACCENT_COLOR}'):
with ui.column().classes('gap-4'):
ui.markdown('Go to the API reference to see a ton of live examples.') \
.style('font-size: 220%; color: white; line-height: 0.9; font-weight: 500')
ui.html('The whole content of nicegui.io is implemented with NiceGUI itself.') \
.style('font-size: 150%; color: white')
ui.link('API reference', '/reference') \
.classes('rounded-full mx-auto px-12 py-2 text-xl text-bold bg-white')
with ui.column().classes('w-full q-pa-xl'):
ui.label('In-depth demonstration').classes('text-bold text-lg')
ui.html('What else can you do with NiceGUI?') \
.style('font-size: 300%; font-weight: 500; margin-top: -20px')
with ui.row().classes('w-full no-wrap text-lg leading-tight'):
with ui.column().classes('w-1/3'):
ui.markdown(
'You may also have a look at the following examples for in-depth demonstrations of what you can do with NiceGUI:')
example_link('Slideshow', 'implements a keyboard-controlled image slideshow')
example_link('Authentication', 'shows how to use sessions to build a login screen')
example_link(
'Modularization',
'provides an example of how to modularize your application into multiple files and create a specialized page decorator')
with ui.column().classes('w-1/3'):
example_link('Map', 'uses the JavaScript library leaflet to display a map at specific locations')
example_link(
'AI Interface',
'utilizes the great but non-async API from to perform voice-to-text transcription and generate images from prompts with Stable Diffusion')
example_link('3D Scene', 'creates a 3D scene and loads an STL mesh illuminated with a spotlight')
with ui.column().classes('w-1/3'):
example_link('Custom Vue Component', 'shows how to write and integrate a custom vue component')
example_link('Image Mask Overlay', 'shows how to overlay an image with a mask')
example_link('Infinite Scroll', 'shows an infinitely scrolling image gallery')
with ui.row() \
.classes('w-full q-pa-md items-center gap-28 p-32 no-wrap') \
.style(f'height: calc(100vh - {HEADER_HEIGHT}); background: {ACCENT_COLOR}'):
with ui.column().classes('gap-6'):
ui.markdown('Why?') \
.style('font-size: 300%; color: white; line-height: 0.9; font-weight: 500').classes('mb-4')
ui.html('''
We 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.
The backend is build on top of
FastAPI,
which itself is based on the ASGI framework
Starlette,
and the ASGI webserver
Uvicorn.
''').style('font-size: 150%; color: white').classes('leading-tight')
ui.html((STATIC / 'happy_face.svg').read_text()).classes('stroke-white').style('width: 1500px')
def example_link(title: str, description: str) -> None:
name = title.lower().replace(' ', '_')
with ui.column().classes('gap-0'):
ui.link(title, f'https://github.com/zauberzeug/nicegui/tree/main/examples/{name}/main.py') \
.classes(replace='text-black text-bold')
ui.markdown(description)
@ui.page('/reference')
def reference_page():
add_head_html()
add_header()
reference.create_full()
ui.run()