Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Hyperdiv – Reactive, immediate-mode web UI framework for Python (github.com/hyperdiv)
170 points by mondrian 11 months ago | hide | past | favorite | 83 comments
Hello HN,

I'm releasing Hyperdiv (https://hyperdiv.io), a framework for rapidly developing reactive browser UIs in Python, with immediate-mode syntax and using Shoelace (https://shoelace.style) as its built-in component system.

This short coding video will give you a good idea of what it is: https://www.youtube.com/watch?v=4XJKfxaqvGE

I wrote a brief article about the motivation and approach: https://hyperdiv.io/intro.html

Hyperdiv doesn't aim to compete with serious full-stack frameworks. The core aim was to make it easy and fast to prototype apps and build UI-based tools. I was originally motivated by internal tools at work -- feeling the need to quickly put together UI-based tools to share with both technical and non-technical coworkers, without having to stand up and maintain a full internal stack.

This is my first major open source release. I really appreciate your feedback and support. - Marius




They hooked me right off the bat with the "intro" clearly stating the "problem" which aligns well with how I view it and reeled me all the way in with "solutions" to those problems that are the exact answers I wanted to see.

The proof is in the pudding but its safe to say I'm ALL THE WAY interested right now.


This looks really nice! I feel like Python's frontend ecosystem is currently exploding. I came across fastUI[1] today as well which looks similar.

1. https://github.com/pydantic/FastUI


Good to have more options, especially for those already using FastAPI. Thanks for sharing this link.


Very cool. That video is impressive, although the audio is superfluous. :-)

Have you tried training an AI chatbot to write Hyperdiv apps? It seems like a good idea, and I'm just wondering whether you've tried it and what the results have been like. I might try it myself.


> although the audio is superfluous.

It's so funny how subjective that is — I liked the audio enough to tell the author about it in a DM. Then I come to HN and read that someone disagrees. :)


Haha - same here. I actualy thought it was a cool audio (though slightly on the louder). Almost feel like there was a rhythm to the developer writing code!


Thanks! I am really interested in this topic, and I think it's really promising. I've experimented with showing GPT-4 how Hyperdiv works via examples and was impressed by how well it was able to produce new apps, and even infer parts of the API I didn't show it. I want to experiment with feeding the entire API into an LLM.

In general I get the impression that this approach, of teaching an LLM a small self-contained API like Hyperdiv's, can work better/less hallucinatory compared to trying to build apps with very large APIs like the DOM API.


Does the task system use threading, multiprocessing, or something else? I.E. can I do IO heavy tasks with this framework?

I'd like to read the docs myself to find out, but it seems like they are not hosted on the website. I can see that I can install the package and run the docs command, but I'd really rather use the web browser I'm already in to explore a new (to me) project's docs.


The task system uses a thread pool as well as an ioloop. So tasks can be normal functions as well as `async def` functions/coroutines.

You can also pass in a custom executor and use processes instead of threads.

Thanks for the feedback wrt docs app.


Thank you for releasing this project. It looks great! I just need to find an excuse to try it out now.


Congrats on the launch!

Just today, I started exploring the current web development ecosystem in Python. As a long-time Python developer, it is amazing to see all the recent work that has gone into making the web accessible to more than just JavaScript developers.

Despite seeing all these amazing new approaches (e.g., Reflex, Streamlit, and now this), I can't help but think there is still a need to rely on "more mature tech" (though this gap is closing) to make non-trivial websites in Python (and in general). After surveying the Python (and JavaScript) ecosystem, I personally decided that a simple stack consisting of FastAPI, Pydantic, SQLAlchemy, Jinja2, Tailwind CSS, and HTMX would be the fastest approach to build a non-trivial app using Python.

With that being said, I will definitely circle back around in a month or so to see how things have progressed. I wish you all the best in making Python a contender for the next generation of web development.


I am trying out a new stack I’m coining “SLAP” for small web apps.

SQLite, Linux, Apache/Nginx, PHP

It’s reminiscent of LAMP, so it’s very easy and cheap to deploy and maintain. I do wish the P stood for python instead of php, but Nginx integrates so well with php and doesn’t require a long running process like PM2 (nodejs) or Gunicorn.


Well unless you use a less traditional setup such as FrankenPHP, in order to run PHP behind a Nginx server you still need a long running process for PHP-FPM, if I'm not wrong? :-)


You're right, it requires PHP-FPM :\


Thanks! In general I'm a big fan of choosing the right tool/stack for the job, and for the developer's natural disposition, and I'm a fan of your choice of stack.


Very cool! I like the immediate mode ui!

Question: does this mean the server is stateful? Or is the state send with every request?


Thanks! Everything happens on the server. The client is a dumb client that just applies incoming patches to the browser dom.


This looks nice. But glaring issue I have is documentation: Don't make people have to pull run code to get at the documentation. Host it somewhere on your website or readthedocs.


Thanks! I appreciate the feedback and plan to host the docs app on the website in the future.


The code in the intro blog post seems to be broken:

Hyperdiv does this:

def my_ui(hide_text=False): button("Button 1") if show_text: text("Hello") button("Button 2")


Yikes, what browser/os? Had a hard time repro-ing.


I think what they mean, is that the function has the argument hide_text, while the if statement uses the variable show_text which is not defined in this scope


Ahh thank you! I fixed it.


Looks cool. How do you see this differing from streamlit? https://streamlit.io/


Thanks! Streamlit is really cool and is obviously mature and successful. It seems to be influenced by Jupyter notebooks and data science practice. It aims to be like Jupyter notebooks but in code? Correct me if I'm wrong.

Hyperdiv is a generic framework with unrestricted layouts (but you can use a template if you want), and a component architecture where all components, whether UI components or internal state, are fundamentally similar and expose stateful props.


What bout Dash? It's also a framework to support UI dev in python. Unlike streamilit, Dash is more for general purpose ui development afaik.


Dash is similar in spirit, as a "build web UIs with Python" framework. Dash seems more similar to nicegui (https://nicegui.io) architecturally than to Hyperdiv. Like nicegui, it builds a static dom that is then mutated via callbacks or data bindings.

By contrast, Hyperdiv lays out UI declaratively based on state, and when state changes, the app re-runs, generating an updated UI. Streamlit and Hyperdiv seem to work similarly, though I'm not sure how Streamlit handles state and state-based layout.


Streamlit reloads and runs the entire app on every change which can make it very slow for data intensive tasks and is hard to work with for complex UIs in my experience


Looks really cool. How easy is it to create custom component or to add custom hooks to existing UI behaviours?


Thanks! Currently you can’t create a new “base” component with custom html/javascript, short of adding it to the hyperdiv source code. I’m working on adding third party component support.


Thanks! I am curious to know why you choose to go with custom communication protocol instead of having a REST endpoint.


We'd love to support this in Ploomber Cloud!

We already support frameworks like Streamlit, Gradio, Shiny, Solara, Voila, among others. Ping me if you're interested!

https://docs.cloud.ploomber.io/en/latest/intro.html


This is really nice. I like the programming model a lot, even if it has some restrictions compared to typical SPA/SSR model.

Makes me realize how webdev is still just teeming with stupid levels of incidental complexity, and I'm not sure I trust webdevs to actually get us out of the tarpit.


Hi Marius. This looks neat, the only big worry I have is about the custom protocol and virtual DOM patching. Do you have thoughts on what it’d take to use plain HTML over the wire instead?


Can you explain why you'd want plain HTML over the wire?

I happen to be working on a standardized protocol (braid-http) for sending diffs over HTTP, and have been thinking about applying it to hyperdiv. I'd love to understand your use-case and what about plain HTML you like here.


Oh neat! I worked on Secure Scuttlebutt, so this is right up my alley. I’ll check out your RFC drafts, thanks for the tip!

Answering your question: it’s mostly the curmudgeonly tendency to avoid custom protocols that are harder to introspect and debug. It’s possible that the hyperdiv sync protocol is super intuitive and simple, but whenever possible I’d like to use boring web standards to reduce the surface area that I’ll feel the need to learn.


Very cool! I resonate with those values!

It also allows standard tools and front-ends to work with any back-end. We could have CDNs that can cache and sync dynamic HTML for a set of users without touching the server.


Thanks! I need to do more research on the available HTML over the wire protocols. In principle Hyperdiv can easily send HTML strings instead of its custom JSON format.


Cool! Is there somewhere I can learn about the custom JSON format? Its possible that I’m just wary because I’m unfamiliar.


It’s not explicitly documented yet. I should do that.

The dom sent over the wire is very similar to html but it’s json.

Then the diff is a json that indicates whether to add children and at which index, whether to remove children and at which index and how many, and attributes to update. This is the part I’m unsure of there being an analogue in protocols like htmx.

Easiest way to see it in action currently is to run a Hyperdiv app, open chrome dev tools and watch the websocket traffic on /ws


this is cool, and a way better executed/more fully featured version of this poc i did a couple weeks ago :) which uses vue under the hood

https://news.ycombinator.com/item?id=39353269

example app: https://github.com/thejchap/pue/blob/main/example.py

good luck! i think there’s definitely something here with this kind of thing


Thanks! Pue looks cool, thanks for sharing. I see some similarities to https://reflex.dev in terms of providing a declarative dom expression language with built-in conditionals and loop primitives.


This seems very intriguing! You might consider putting your neat screenshot gifs around more places to make it easier to see the value. What are your thoughts on async vs your current approach?

I'm curious, why you went with Shoelace? Was there anything else you considered instead? Doing things at the right level is tricky. I'm just curious how you arrived at the level you've got with Shoelace in Hyperdiv, over others. Nice work!


Thanks! What do you mean by async?

At one point Hyperdiv’s frontend was using Svelte and Svelte Material UI components. I explored other options before settling on shoelace.

Shoelace stuck primarily because it’s very solid and uniform. Ran into very few issues attempting to integrate it. And it being web components allows for a clean and straightforward vanilla JS frontend without dependencies on frontend frameworks. (I love Svelte a lot, but the Hyperdiv Svelte frontend was pretty gnarly.)


That makes sense, and it makes me wonder what you think about Nicegui, if anything?

Re: Async - there could potentially be speed benefits and simplifications if async interfaces were exposed instead of synchronous functions, right? Maybe it's not more simple, maybe async is a trap for the use cases you see that would overcomplicate (totally possible)? Being able to do stuff like await multiple API requests to LLM's and deal with the first to return, or wait for both, is the kinda thing that Python's async interfaces can make easier and I notice that you're already using Tornado for websockets under the hood, which is natively async I think, but the Hyperdiv examples I saw weren't using async functions so I wondered about what the side effects of that could be. Maybe you already have exposed interfaces for it and I've just overlooked them? Edit: I just noticed you said you have async function support! Well, I wonder how deep it goes? I guess you know when something breaks? Anyway really nice presentation of the problem and solution, nice work!


Thanks!

Re: nicegui, I like nicegui. Hyperdiv and nicegui are similar in that they're "build web UIs in Python" frameworks but take significantly different approaches. See this comment: https://news.ycombinator.com/item?id=39458641

Re: async. Hyperdiv's main function, which generates the UI, runs synchronously, indeed. But the main function can spawn off asynchronous calls. For example:

    async def api_call():
        data = await get_data()
        return data

    def main():
        task = hd.task()
        task.run(api_call)
        if not task.done:
            hd.spinner()
        else:
            hd.text("Loaded data:", task.result)
This app spins off an async call to api_call(). While the call is running in the background, a loading spinner is displayed. When the task finishes, its return value is rendered.

Async tasks can also update state gradually while they run:

    async def api_calls(state):
        data1 = await get_data1()
        state.data1 = data1
        data2 = await get_data2()
        state.data2 = data2

    def main():
        state = hd.state(data1=None, data2=None)
        task = hd.task()
        task.run(api_calls, state)
        hd.text("Data1:", state.data1)
        hd.text("Data2:", state.data2)
This app will initially display "Data1: None\nData2: None". When get_data1() finishes running, the UI updates to show the result for "Data1", but the result for "Data2" is still None. When `get_data2()` finishes running, both fields are then filled.

You can also write an async function that runs indefinitely, continually listening on some I/O channel and updating state as new data arrives. When the app exits, it can signal the task to exit.


That's cool and I imagine it supports a lot of the situations async users would need. Thanks for your great explanation. Having a more clean, declarative state is a great differentiation from Nicegui. This is a great contribution, I wish you the best of luck to you!


Looks super cool! Clearly an idea that people want - I built something similar to this almost two year ago [1] but your project is a lot more fleshed out. I like that you actually used websockets instead of my hacky approach of using an http stream.

[1] https://gitlab.com/BenWiser/python-live-gui


Thanks! I like your project! Similar idea, indeed.


Way to go, Marius!

This scratches a good itch that Streamlit just seems to baaaaaaaaaaaarely miss -- more fine-grained control of the React under the hood.

Keep it up!


So is this basically elixir’s Phoenix framework?

One key feature of BEAM, has always been its ability to sustain high user count with this architecture, as its totally ok to have “a thread per user” on your server.

Wondering now how hyperdiv scales to thousands/millions of users, given python’s inherently stateful nature, what’s the key tech that made it possible?


Hyperdiv uses one thread per connection and it’s true that a Python process may not be great at running a very large number of threads. Currently you can scale a Hyperdiv app horizontally by running it in multiple processes (on multiple machines) behind a load balancer.


Very cool. Looks even closer to Reflex (maybe Flet in web mode?) than Streamlit... Could someone with Reflex experience comment on the difference?

Separately, all of the above seem to lack official auth solutions. People with experience in all of these, do you just roll your own or integrate with something else?


As far as comparing to Reflex: In a nutshell, Reflex statically compiles the app to Javascript, which then runs in the browser. Event handlers and state changes happen in Python, and UI logic happens in the browser.

By contrast, Hyperdiv runs everything in Python and ships DOM and DOM patches to the browser.


looks neat. it would help if you hosted the demo apps rather than expecting the user to install and run them themselves to get a feel for it

https://github.com/hyperdiv/hyperdiv-apps/tree/main


Thanks! I plan on putting the demo apps and docs app online.


Seems similar to Justpy or Nicegui.


Very interesting to see similar projects! Different ways of solving similar problems helps understand the problem/solution space better. It seems like Nicegui continues Justpy development.


This is really cool, I wish I could already use it in production. I will wait until we can add/modify components, but this looks really awesome.


This looks amazing Wanted to build something using HTMX first, but this seems like a great fullstack solution for simple UI's, like a Fullstack version of HTMX fully built with python


Congratulation on your release. Tried it a bit, very promising to me.

Anyway, I tried to look around and it seem to be lacked any component to upload files. Is it in the pipeline or I missed something?


Thanks! There’s no file upload component currently but I plan to add it soon.


Would love to use something like this directly from within Django views without having to use standard templating. Any thoughts on how to best accomplish such a setup...?


I don’t have experience with Django but this sounds interesting, I’ll do some research. In general, being able to integrate Hyperdiv selectively into existing stacks would be cool. Currently you could probably do it with an iframe, which works but is not ideal.


"Tetra Framework", "a full stack component framework for Django using Alpine.js" might be informative: https://www.tetraframework.com


Thanks!


I'd love this too!


This is really cool, congrats on shipping it.

I hadn't heard of shoelace before, but I love how easily you split things out into named components in the demo. Really cool mix of tech


Great work! I'm very interested as I don't like UI programming and I like the simplicity of immediate mode.


I like the concept of not having to collect UI elements ins data structure; very elegant and I’m now very curious :)


Looks cool. I'd suggest putting a minimal code example and screenshot in both the repo and homepage.


Thanks! I will do that.


Why do I have to download it before I can read the documentation or see any demos?


I plan on putting those online. I haven't yet set up the hosting infrastructure to serve Hyperdiv apps off my linodes. That and some of the demo apps are currently designed as local apps that edit local files on disk, and/or not yet multi-user ready. E.g., the markdown app works like a command-line tool that you point to a local markdown file.


How does this compare to something like the NiceGUI framework?


It seems in nicegui you build the initial UI, and then mutate various parts of it in event callbacks. It seems similar to traditional dom programming.

Hyperdiv expresses UI declaratively based on state. As state changes, the app re-runs, producing a changed UI.


This is really impressive


Holy crap that was cool. Very nice demo. Why would this not be a streamlit competitor. Also some part of me is thinking there would be a huge synergy (yuck i hated using that word) by htmx being involved here somehow?


or an alternative to nicegui.

I fully agree that it is a great project and that there is plenty of space to have different frameworks with their specialties that allow to choose the best one based on the circumstances.


A big Streamlit competitor right now is gradio, which is especially popular for machine learning demos and makes prototyping very easy, they have a very active community


I run into friction with Streamlit and Gradio that make me less interested in it, so I'm very interested in alternatives that are similarly concise but more powerful.


Thanks!

> htmx being involved

I think it's possible. Hyperdiv uses a custom DOM patching system but I could imagine it being swapped for an existing HTML over the wire tech.


just to add some thoughts here, because that was my first reaction as well, to think of mixing this with htmx... but after some thoughts, I am wondering how much this would be really useful, because the main benefit of htmx when writing html. Writing html being the key. Here we are writing python.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: