main.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #!/usr/bin/env python3
  2. from pathlib import Path
  3. import docutils.core
  4. from pygments.formatters import HtmlFormatter
  5. from nicegui import Client, ui
  6. from website import demo_card, reference
  7. from website.constants import ACCENT_COLOR, HEADER_HEIGHT, STATIC
  8. from website.example import bash_window, python_window
  9. ui.add_static_files('/favicon', Path(__file__).parent / 'website' / 'favicon')
  10. def add_head_html() -> None:
  11. ui.add_head_html('<meta name="viewport" content="width=device-width, initial-scale=1" />')
  12. ui.add_head_html(docutils.core.publish_parts('', writer_name='html')['stylesheet'])
  13. ui.add_head_html(f'<style>{HtmlFormatter(nobackground=True).get_style_defs(".codehilite")}</style>')
  14. ui.add_head_html('''
  15. <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
  16. <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
  17. <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
  18. <link rel="manifest" href="/favicon/site.webmanifest">
  19. <link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#000000">
  20. <link rel="shortcut icon" href="/favicon/favicon.ico">
  21. <meta name="msapplication-TileColor" content="#ffffff">
  22. <meta name="msapplication-config" content="/favicon/browserconfig.xml">
  23. <meta name="theme-color" content="#ffffff">
  24. ''') # https://realfavicongenerator.net/
  25. ui.add_head_html(f'''
  26. <style>
  27. html {{
  28. scroll-behavior: smooth;
  29. }}
  30. body {{
  31. background-color: #f8f8f8;
  32. }}
  33. em {{
  34. font-style: normal;
  35. color: {ACCENT_COLOR};
  36. }}
  37. a:hover {{
  38. opacity: 0.9;
  39. }}
  40. </style>
  41. ''')
  42. ui.add_head_html(f'''
  43. <style>
  44. .q-header {{
  45. height: calc({HEADER_HEIGHT} + 20px);
  46. background-color: {ACCENT_COLOR};
  47. }}
  48. .q-header.fade {{
  49. height: {HEADER_HEIGHT};
  50. background-color: {ACCENT_COLOR}d0;
  51. backdrop-filter: blur(5px);
  52. }}
  53. </style>
  54. <script>
  55. window.onscroll = () => {{
  56. const header = document.querySelector(".q-header");
  57. if (document.documentElement.scrollTop > 50)
  58. header.classList.add("fade");
  59. else
  60. header.classList.remove("fade");
  61. }};
  62. </script>
  63. ''')
  64. def add_header() -> None:
  65. with ui.header() \
  66. .classes('items-center duration-200 px-4', remove='q-pa-md') \
  67. .style('box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1)'):
  68. ui.html((STATIC / 'happy_face.svg').read_text()).classes('w-8 stroke-white')
  69. with ui.link(target=index_page):
  70. ui.html((STATIC / 'nicegui_word.svg').read_text()).classes('w-24')
  71. with ui.row().classes('items-center ml-auto'):
  72. ui.link('Features', '/#features').classes(replace='text-lg text-white')
  73. ui.link('Installation', '/#installation').classes(replace='text-lg text-white')
  74. ui.link('Examples', '/#examples').classes(replace='text-lg text-white')
  75. ui.link('API Reference', reference_page).classes(replace='text-lg text-white')
  76. with ui.link(target='https://github.com/zauberzeug/nicegui/'):
  77. ui.html((STATIC / 'github.svg').read_text()).classes('fill-white scale-125 m-1')
  78. @ui.page('/')
  79. async def index_page(client: Client):
  80. client.content.classes(remove='q-pa-md gap-4')
  81. add_head_html()
  82. add_header()
  83. with ui.row() \
  84. .classes('w-full h-screen q-pa-md items-center gap-12 no-wrap') \
  85. .style(f'transform: translateX(-250px)'):
  86. ui.html((STATIC / 'happy_face.svg').read_text()).classes('stroke-black').style('width: 500px')
  87. with ui.column().classes('gap-8'):
  88. ui.html('Meet the <em>NiceGUI</em>.') \
  89. .style('font-size: 400%; line-height: 0.9; font-weight: 500')
  90. ui.markdown('Your easy-to-use Python framework to create\n\nuser interfaces which show up in the browser.') \
  91. .style('font-size: 200%; line-height: 0.9')
  92. with ui.row() \
  93. .classes('w-full h-screen q-pa-md items-center gap-28 p-32 no-wrap') \
  94. .style(f'background: {ACCENT_COLOR}'):
  95. with ui.column().classes('gap-6'):
  96. ui.markdown('Create buttons, dialogs, markdown,\n\n3D scenes, plots and much more at ease.') \
  97. .style('font-size: 300%; color: white; line-height: 0.9; font-weight: 500').classes('mb-4')
  98. ui.label('''
  99. It is great for micro web apps, dashboards, robotics projects, smart home solutions
  100. and similar use cases. You can also use it in development, for example when
  101. tweaking/configuring a machine learning algorithm or tuning motor controllers.
  102. ''').style('font-size: 150%; color: white').classes('leading-tight')
  103. with ui.row().style('font-size: 150%; color: white').classes('leading-tight gap-2'):
  104. ui.html('''
  105. NiceGUI is available as
  106. <a href="https://pypi.org/project/nicegui/"><strong>PyPI package</strong><span class="material-icons">north_east</span></a>,
  107. <a href="https://hub.docker.com/r/zauberzeug/nicegui"><strong>Docker image</strong><span class="material-icons">north_east</span></a> and on
  108. <a href="https://github.com/zauberzeug/nicegui"><strong>GitHub</strong><span class="material-icons">north_east</span></a>.
  109. ''')
  110. demo_card.create()
  111. ui.link_target('features').style(f'position: relative; top: -{HEADER_HEIGHT}')
  112. with ui.column().classes('w-full q-pa-xl'):
  113. ui.label('Features').classes('text-bold text-lg')
  114. ui.html('What has <em>NiceGUI</em> to offer?') \
  115. .style('font-size: 300%; font-weight: 500; margin-top: -20px')
  116. with ui.row().classes('w-full no-wrap text-lg leading-tight justify-between'):
  117. with ui.column().classes('gap-1'):
  118. ui.label('User Interface').classes('text-bold mb-4')
  119. ui.markdown('- common elements like label, button, checkbox, switch, slider, input, ...')
  120. ui.markdown('- page layout with navigation bars, tabs, panels, ...')
  121. ui.markdown('- grouping with rows, columns, cards and dialogs')
  122. ui.markdown('- HTML and markdown elements')
  123. ui.markdown('- high-level elements like charts, tables, trees, 3D scenes, joystick, ...')
  124. ui.markdown('- built-in timer to refresh data in intervals')
  125. ui.markdown('- notifications, dialogs and menus')
  126. ui.markdown('- keyboard input')
  127. with ui.column().classes('gap-1'):
  128. ui.label('Under the hood').classes('text-bold mb-4')
  129. ui.markdown('- browser-based graphical user interface')
  130. ui.markdown('- based on FastAPI and Uvicorn')
  131. ui.markdown('- live-cycle events and session data')
  132. ui.markdown('- customizable page layout and colors')
  133. with ui.column().classes('gap-1'):
  134. ui.label('Development').classes('text-bold mb-4')
  135. ui.markdown('- implicit reload on code change')
  136. ui.markdown('- straight-forward data binding')
  137. ui.link_target('installation').style(f'position: relative; top: -{HEADER_HEIGHT}')
  138. with ui.column().classes('w-full q-pa-xl'):
  139. ui.label('Installation').classes('text-bold text-lg')
  140. ui.html('Getting <em>started</em>') \
  141. .style('font-size: 300%; font-weight: 500; margin-top: -20px')
  142. with ui.row().classes('w-full no-wrap text-lg leading-tight'):
  143. with ui.column().classes('w-1/3 gap-2'):
  144. ui.html('<em>1.</em>').classes('text-3xl text-bold')
  145. ui.markdown('Install').classes('text-lg')
  146. with bash_window().classes('w-full h-52'):
  147. ui.markdown('```bash\npython3 -m pip install nicegui\n```')
  148. with ui.column().classes('w-1/3 gap-2'):
  149. ui.html('<em>2.</em>').classes('text-3xl text-bold')
  150. ui.markdown('Write file __main.py__').classes('text-lg')
  151. with python_window().classes('w-full h-52'):
  152. ui.markdown('''```python\n
  153. from nicegui import ui
  154. ui.label('Hello NiceGUI!')
  155. ui.run()
  156. ```''')
  157. with ui.column().classes('w-1/3 gap-2'):
  158. ui.html('<em>3.</em>').classes('text-3xl text-bold')
  159. ui.markdown('Launch it with').classes('text-lg')
  160. with bash_window().classes('w-full h-52'):
  161. ui.markdown('```bash\npython3 main.py\n```')
  162. ui.link_target('examples').style(f'position: relative; top: -{HEADER_HEIGHT}')
  163. with ui.column().classes('w-full q-pa-xl'):
  164. ui.label('Documentation').classes('text-bold text-lg')
  165. ui.html('Interactive <em>Examples</em>') \
  166. .style('font-size: 300%; font-weight: 500; margin-top: -20px')
  167. reference.create_intro()
  168. with ui.row() \
  169. .classes('w-full items-center gap-28 px-32 py-16 no-wrap') \
  170. .style(f'background: {ACCENT_COLOR}'):
  171. with ui.column().classes('gap-4'):
  172. ui.markdown('Go to the API reference to see a ton of live examples.') \
  173. .style('font-size: 220%; color: white; line-height: 0.9; font-weight: 500')
  174. ui.html('The whole content of <a href="https://nicegui.io/">nicegui.io</a> is implemented with NiceGUI itself.') \
  175. .style('font-size: 150%; color: white')
  176. ui.link('API reference', '/reference') \
  177. .classes('rounded-full mx-auto px-12 py-2 text-xl text-bold bg-white')
  178. with ui.column().classes('w-full q-pa-xl'):
  179. ui.label('In-depth demonstration').classes('text-bold text-lg')
  180. ui.html('What else can you do with <em>NiceGUI</em>?') \
  181. .style('font-size: 300%; font-weight: 500; margin-top: -20px')
  182. with ui.row().classes('w-full no-wrap text-lg leading-tight'):
  183. with ui.column().classes('w-1/3'):
  184. ui.markdown(
  185. 'You may also have a look at the following examples for in-depth demonstrations of what you can do with NiceGUI:')
  186. example_link('Slideshow', 'implements a keyboard-controlled image slideshow')
  187. example_link('Authentication', 'shows how to use sessions to build a login screen')
  188. example_link(
  189. 'Modularization',
  190. 'provides an example of how to modularize your application into multiple files and create a specialized page decorator')
  191. with ui.column().classes('w-1/3'):
  192. example_link('Map', 'uses the JavaScript library leaflet to display a map at specific locations')
  193. example_link(
  194. 'AI Interface',
  195. 'utilizes the great but non-async API from <https://replicate.com> to perform voice-to-text transcription and generate images from prompts with Stable Diffusion')
  196. example_link('3D Scene', 'creates a 3D scene and loads an STL mesh illuminated with a spotlight')
  197. with ui.column().classes('w-1/3'):
  198. example_link('Custom Vue Component', 'shows how to write and integrate a custom vue component')
  199. example_link('Image Mask Overlay', 'shows how to overlay an image with a mask')
  200. example_link('Infinite Scroll', 'shows an infinitely scrolling image gallery')
  201. with ui.row() \
  202. .classes('w-full h-screen q-pa-md items-center gap-28 p-32 no-wrap') \
  203. .style(f'background: {ACCENT_COLOR}'):
  204. with ui.column().classes('gap-6'):
  205. ui.markdown('Why?') \
  206. .style('font-size: 300%; color: white; line-height: 0.9; font-weight: 500').classes('mb-4')
  207. ui.html('''
  208. We like
  209. <strong><a href="https://streamlit.io/">Streamlit</a></strong>
  210. but find it does
  211. <strong><a href="https://github.com/zauberzeug/nicegui/issues/1#issuecomment-847413651">too much magic</a></strong>
  212. when it comes to state handling.
  213. In search for an alternative nice library to write simple graphical user interfaces in Python we discovered
  214. <strong><a href="https://justpy.io/">JustPy</a></strong>.
  215. Although we liked the approach, it is too "low-level HTML" for our daily usage.
  216. But it inspired us to use
  217. <strong><a href="https://vuejs.org/">Vue</a></strong>
  218. and
  219. <strong><a href="https://quasar.dev/">Quasar</a></strong>
  220. for the frontend.<br/>
  221. The backend is build on top of
  222. <strong><a href="https://fastapi.tiangolo.com/">FastAPI</a></strong>,
  223. which itself is based on the ASGI framework
  224. <strong><a href="https://www.starlette.io/">Starlette</a></strong>,
  225. and the ASGI webserver
  226. <strong><a href="https://www.uvicorn.org/">Uvicorn</a></strong>.
  227. ''').style('font-size: 150%; color: white').classes('leading-tight')
  228. ui.html((STATIC / 'happy_face.svg').read_text()).classes('stroke-white').style('width: 1500px')
  229. def example_link(title: str, description: str) -> None:
  230. name = title.lower().replace(' ', '_')
  231. with ui.column().classes('gap-0'):
  232. ui.link(title, f'https://github.com/zauberzeug/nicegui/tree/main/examples/{name}/main.py') \
  233. .classes(replace='text-black text-bold')
  234. ui.markdown(description)
  235. @ui.page('/reference')
  236. def reference_page():
  237. add_head_html()
  238. add_header()
  239. reference.create_full()
  240. ui.run()