main.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #!/usr/bin/env python3
  2. if True:
  3. # increasing max decode packets to be able to transfer images
  4. # see https://github.com/miguelgrinberg/python-engineio/issues/142
  5. from engineio.payload import Payload
  6. Payload.max_decode_packets = 500
  7. import os
  8. from pathlib import Path
  9. from pygments.formatters import HtmlFormatter
  10. import prometheus
  11. from nicegui import Client, app
  12. from nicegui import globals as nicegui_globals
  13. from nicegui import ui
  14. from website import demo_card, reference, svg
  15. from website.example import bash_window, browser_window, python_window
  16. from website.style import example_link, features, heading, link_target, section_heading, subtitle, title
  17. prometheus.start_monitor(app)
  18. ui.add_static_files('/favicon', str(Path(__file__).parent / 'website' / 'favicon'))
  19. ui.add_static_files('/fonts', str(Path(__file__).parent / 'website' / 'fonts'))
  20. # NOTE in our global fly.io deployment we need to make sure that the websocket connects back to the same instance
  21. fly_instance_id = os.environ.get('FLY_ALLOC_ID', '').split('-')[0]
  22. if fly_instance_id:
  23. nicegui_globals.socket_io_js_extra_headers['fly-force-instance-id'] = fly_instance_id
  24. def add_head_html() -> None:
  25. ui.add_head_html((Path(__file__).parent / 'website' / 'static' / 'header.html').read_text())
  26. ui.add_head_html(f'<style>{HtmlFormatter(nobackground=True).get_style_defs(".codehilite")}</style>')
  27. ui.add_head_html(f"<style>{(Path(__file__).parent / 'website' / 'static' / 'style.css').read_text()}</style>")
  28. def add_header() -> None:
  29. menu_items = {
  30. 'Features': '/#features',
  31. 'Installation': '/#installation',
  32. 'Examples': '/#examples',
  33. 'API Reference': '/reference',
  34. 'Demos': '/#demos',
  35. 'Why?': '/#why',
  36. }
  37. with ui.header() \
  38. .classes('items-center duration-200 p-0 px-4 no-wrap') \
  39. .style('box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1)'):
  40. with ui.link(target=index_page).classes('row gap-4 items-center no-wrap mr-auto'):
  41. svg.face().classes('w-8 stroke-white stroke-2')
  42. svg.word().classes('w-24')
  43. with ui.row().classes('lg:hidden'):
  44. with ui.menu().classes('bg-primary text-white text-lg') as menu:
  45. for title, target in menu_items.items():
  46. ui.menu_item(title, on_click=lambda _, target=target: ui.open(target))
  47. ui.button(on_click=menu.open).props('flat color=white icon=menu')
  48. with ui.row().classes('max-lg:hidden'):
  49. for title, target in menu_items.items():
  50. ui.link(title, target).classes(replace='text-lg text-white')
  51. with ui.link(target='https://github.com/zauberzeug/nicegui/'):
  52. svg.github().classes('fill-white scale-125 m-1')
  53. @ui.page('/')
  54. async def index_page(client: Client):
  55. client.content.classes(remove='q-pa-md gap-4')
  56. add_head_html()
  57. add_header()
  58. with ui.row().classes('w-full h-screen items-center gap-8 pr-4 no-wrap into-section'):
  59. svg.face(half=True).classes('stroke-black w-[200px] md:w-[230px] lg:w-[300px]')
  60. with ui.column().classes('gap-4 md:gap-8 pt-32'):
  61. title('Meet the *NiceGUI*.')
  62. subtitle('And let any browser be the frontend of your Python code.') \
  63. .classes('max-w-[20rem] sm:max-w-[24rem] md:max-w-[30rem]')
  64. ui.link(target='#about').classes('scroll-indicator')
  65. with ui.row().classes('''
  66. dark-box min-h-screen no-wrap
  67. justify-center items-center flex-col md:flex-row
  68. py-20 px-8 lg:px-16
  69. gap-8 sm:gap-16 md:gap-8 lg:gap-16
  70. '''):
  71. link_target('about')
  72. with ui.column().classes('text-white max-w-4xl'):
  73. heading('Interact with Python through buttons, dialogs, 3D&nbsp;scenes, plots and much more.')
  74. with ui.column().classes('gap-2 bold-links arrow-links text-lg'):
  75. ui.markdown(
  76. 'NiceGUI handles all the web development details for you. '
  77. 'So you can focus on writing Python code. '
  78. 'Anything from short scripts and dashboards to full robotics projects, IoT solutions, '
  79. 'smart home automations and machine learning projects can benefit from having all code in one place.'
  80. )
  81. ui.markdown(
  82. 'Available as '
  83. '[PyPI package](https://pypi.org/project/nicegui/), '
  84. '[Docker image](https://hub.docker.com/r/zauberzeug/nicegui) and on '
  85. '[GitHub](https://github.com/zauberzeug/nicegui).')
  86. demo_card.create()
  87. with ui.column().classes('w-full p-8 lg:p-16 bold-links arrow-links max-w-[1600px] mx-auto'):
  88. link_target('features', '-50px')
  89. section_heading('Features', 'Code *nicely*')
  90. with ui.row().classes('w-full text-lg leading-tight grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-8'):
  91. features('swap_horiz', 'Interaction', [
  92. 'buttons, switches, sliders, inputs, ...',
  93. 'notifications, dialogs and menus',
  94. 'keyboard input',
  95. 'on-screen joystick',
  96. ])
  97. features('space_dashboard', 'Layout', [
  98. 'navigation bars, tabs, panels, ...',
  99. 'grouping with rows, columns and cards',
  100. 'HTML and markdown elements',
  101. 'flex layout by default',
  102. ])
  103. features('insights', 'Visualization', [
  104. 'charts, diagrams and tables',
  105. '3D scenes',
  106. 'progress bars',
  107. 'built-in timer for data refresh',
  108. ])
  109. features('brush', 'Styling', [
  110. 'customizable color themes',
  111. 'custom CSS and classes',
  112. 'modern look with material design',
  113. 'built-in [Tailwind](https://tailwindcss.com/) support',
  114. ])
  115. features('source', 'Coding', [
  116. 'live-cycle events',
  117. 'implicit reload on code change',
  118. 'straight-forward data binding',
  119. 'execute javascript from Python',
  120. ])
  121. features('anchor', 'Foundation', [
  122. 'generic [Vue](https://vuejs.org/) to Python bridge',
  123. 'dynamic GUI through [Quasar](https://quasar.dev/)',
  124. 'content is served with [FastAPI](http://fastapi.tiangolo.com/)',
  125. 'Python 3.7+',
  126. ])
  127. with ui.column().classes('w-full p-8 lg:p-16 max-w-[1600px] mx-auto'):
  128. link_target('installation', '-50px')
  129. section_heading('Installation', 'Get *started*')
  130. with ui.row().classes('w-full text-lg leading-tight grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-8'):
  131. with ui.column().classes('w-full max-w-md gap-2'):
  132. ui.html('<em>1.</em>').classes('text-3xl font-bold')
  133. ui.markdown('Create __main.py__').classes('text-lg')
  134. with python_window(classes='w-full h-52'):
  135. ui.markdown('''```python\n
  136. from nicegui import ui
  137. ui.label('Hello NiceGUI!')
  138. ui.run()
  139. ```''')
  140. with ui.column().classes('w-full max-w-md gap-2'):
  141. ui.html('<em>2.</em>').classes('text-3xl font-bold')
  142. ui.markdown('Install and launch').classes('text-lg')
  143. with bash_window(classes='w-full h-52'):
  144. ui.markdown('```bash\npip3 install nicegui\npython3 main.py\n```')
  145. with ui.column().classes('w-full max-w-md gap-2'):
  146. ui.html('<em>3.</em>').classes('text-3xl font-bold')
  147. ui.markdown('Enjoy!').classes('text-lg')
  148. with browser_window(classes='w-full h-52'):
  149. ui.label('Hello NiceGUI!')
  150. with ui.column().classes('w-full p-8 lg:p-16 max-w-[1600px] mx-auto'):
  151. link_target('examples', '-50px')
  152. section_heading('Examples', 'Try *this*')
  153. with ui.column().classes('w-full'):
  154. reference.create_intro()
  155. with ui.column().classes('dark-box p-8 lg:p-16 my-16'):
  156. with ui.column().classes('mx-auto items-center gap-y-8 gap-x-32 lg:flex-row'):
  157. with ui.column().classes('gap-1 max-lg:items-center max-lg:text-center'):
  158. ui.markdown('Browse through plenty of live examples.') \
  159. .classes('text-white text-2xl md:text-3xl font-medium')
  160. ui.html('Fun-Fact: This whole website is also coded with NiceGUI.') \
  161. .classes('text-white text-lg md:text-xl')
  162. ui.link('API reference', '/reference') \
  163. .classes('rounded-full mx-auto px-12 py-2 text-white bg-white font-medium text-lg md:text-xl')
  164. with ui.column().classes('w-full p-8 lg:p-16 max-w-[1600px] mx-auto'):
  165. link_target('demos', '-50px')
  166. section_heading('In-depth demonstrations', 'Pick your *solution*')
  167. with ui.row().classes('w-full text-lg leading-tight grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4'):
  168. example_link('Slideshow', 'implements a keyboard-controlled image slideshow')
  169. example_link('Authentication', 'shows how to use sessions to build a login screen')
  170. example_link(
  171. 'Modularization',
  172. 'provides an example of how to modularize your application into multiple files and reuse code')
  173. example_link(
  174. 'FastAPI',
  175. 'illustrates the integration of NiceGUI with an existing FastAPI application')
  176. example_link(
  177. 'Map',
  178. 'demonstrates wrapping the JavaScript library [leaflet](https://leafletjs.com/) to display a map at specific locations')
  179. example_link(
  180. 'AI Interface',
  181. 'utilizes the [replicate](https://replicate.com) library to perform voice-to-text transcription and generate images from prompts with Stable Diffusion')
  182. example_link('3D Scene', 'creates a webGL view and loads an STL mesh illuminated with a spotlight')
  183. example_link('Custom Vue Component', 'shows how to write and integrate a custom Vue component')
  184. example_link('Image Mask Overlay', 'shows how to overlay an image with a mask')
  185. example_link('Infinite Scroll', 'presents an infinitely scrolling image gallery')
  186. example_link('OpenCV Webcam', 'uses OpenCV to capture images from a webcam')
  187. example_link('SVG Clock', 'display an analog clock by updating an svg with `ui.timer`')
  188. with ui.row().classes('bg-primary w-full min-h-screen mt-16'):
  189. link_target('why')
  190. with ui.column().classes('''
  191. max-w-[1600px] m-auto
  192. py-20 px-8 lg:px-16
  193. items-center justify-center no-wrap flex-col md:flex-row gap-16
  194. '''):
  195. with ui.column().classes('gap-8'):
  196. heading('Why?')
  197. with ui.column().classes('gap-2 text-xl text-white bold-links arrow-links'):
  198. ui.markdown(
  199. 'We at '
  200. '[Zauberzeug](https://zauberzeug.com) '
  201. 'like '
  202. '[Streamlit](https://streamlit.io/) '
  203. 'but find it does '
  204. '[too much magic](https://github.com/zauberzeug/nicegui/issues/1#issuecomment-847413651) '
  205. 'when it comes to state handling. '
  206. 'In search for an alternative nice library to write simple graphical user interfaces in Python we discovered '
  207. '[JustPy](https://justpy.io/). '
  208. 'Although we liked the approach, it is too "low-level HTML" for our daily usage. '
  209. 'But it inspired us to use '
  210. '[Vue](https://vuejs.org/) '
  211. 'and '
  212. '[Quasar](https://quasar.dev/) '
  213. 'for the frontend.')
  214. ui.markdown(
  215. 'We have built on top of '
  216. '[FastAPI](https://fastapi.tiangolo.com/), '
  217. 'which itself is based on the ASGI framework '
  218. '[Starlette](https://www.starlette.io/) '
  219. 'and the ASGI webserver '
  220. '[Uvicorn](https://www.uvicorn.org/) '
  221. 'because of their great performance and ease of use.'
  222. )
  223. svg.face().classes('stroke-white shrink-0 w-[200px] md:w-[300px] lg:w-[450px]')
  224. @ui.page('/reference')
  225. def reference_page():
  226. add_head_html()
  227. add_header()
  228. ui.add_head_html('<style>html {scroll-behavior: auto;}</style>')
  229. with ui.column().classes('w-full p-8 lg:p-16 max-w-[1250px] mx-auto'):
  230. section_heading('Documentation and Examples', '*API* Reference')
  231. ui.markdown(
  232. 'This is the API reference for NiceGUI >= 1.0. '
  233. 'Documentation for older versions can be found at [https://0.9.nicegui.io/](https://0.9.nicegui.io/reference).'
  234. ).classes('bold-links arrow-links')
  235. reference.create_full()
  236. ui.run(uvicorn_reload_includes='*.py, *.css, *.html')