Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (Solve) libraries that form a framework when put together even though they don’t depend on each other.
Currently only Linux is supported, to be precise Wayland and DRM (Nerves). MacOS and Windows support is planned sometime in the future. Tested only with AMD (Wayland and DRM), rpi5 and rk3566 nerves devices (DRM)
There is also a Solve LiveView adapter in the works, you will have to ask @ken-kost for the timeline on that.
If you want more details check out on hex and github. Rest of the post will be on hows and whys of development.
Getting artificial elephant out of the room
Before I get any further, this project was a successful experiment on how far I can push gen AI coding. 90%+ of the code in those repos is LLM generated and I could maybe credit it for about 5% of the engineering behind that code, there were sessions with 50+ prompts in plan mode before implementation. I have a pretty good understanding of how incapable AI is. That being sad I still have some coding standards and these projects don’t meet them but that is a future me cleanup problem. If this has made you lose all interest I fully respect that. However this post is 0% AI. I will not even use it for spelling & grammar. I have enough trauma of trying to use LLMs to write the docs and I still hate current state of docs. We can start a new thread if anyone wants more details on AI usage, I would like to keep this one focused on GUI.
Motivation
I use nerves both Professionally and all my hobby projects are tied to it, all of those require UI running on nerves devices and I need/want them to be both easy and fun to develop and high performance at the same time. I also have aspirations to develop a mix of OBS and real-time Davinci Resolve using this system on top of membrane, foundation for video pipelines is already in there.
I have spend half of my career building UIs. Using native Android/iOS, meteor.js, Elm, React, ReactNative, Flutter, Surface/LiveView, Keechma-next(Clojure/Script) in various combinations of state managements and different css frameworks/UI toolkits between all of it.
Most of these tools share a common trait. They are painful to use or turn painful to use as UI becomes complex, each set of tradeoffs falls apart in one way or the other. These 2 are most pleasant from both sides:
- Elm-ui is only lib where I could basically one shot full page from the design without ever running it and it would turn out mostly correct. Emerge API is based on it. When used in Elm this lib becomes painful because elm pushes you into prop drilling.
- Keechma-next had the most pleasant state management solution of them all. It achieves full decoupling of UI and state without prop drilling while having explicit and declarative data flow in a way that scales very well with complexity. Solve is an attempt at 1:1 elixir re-implementation.
It boils down to me wishing for a combination of those 2 every time I have to write an UI. Last time I was building a larger feature in flutter for nerves device just tipped me over and I have decided to just go for it.
Implementation
Emerge is mostly a Rust NIF backed by skia.
You declare a recursive struct in elixir via function based DSL. Struct is diffed with previous version in Elixir, diff is then serialized into binary and sent over to the Rustler NIF.
Rust side consists of the layout engine, renderer and event engine.
Different back-end implementations need to provide renderer with surface to render into and they need to provide output to the event engine.
Hope some of you find this project useful even as it is in this initial version. There is a lot of essential features still missing. More backends and features are coming in the future along with performance optimizations as there is some low-hanging fruit on that side.
If you try it out and are unable to implement a UI feature you want using Emerge feel free to reach out and propose a new feature.
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Asd
So far it looks really cool, do you have any examples which showcase most of the available features? What coding agents have implemented the library, what setup was used?
Damirados
Checkout GitHub - emerge-elixir/emerge_demo: Example showcase app built with Emerge and Solve · GitHub. There is a showcase app in there that covers all of the components and attributes.
I tried lot of models and harnesses in the beginning, settled on Opencode + 5.3Codex, 5.4 later.
derek-zhou
So how much, if anything, is written by AI? 90%+, 5%, or 0%?
Damirados
Sorry, words got lost there, edited. This post is 0% AI. Code is mostly written by AI but it ended up being more of an automatic text editor because I had to have it refactor same thing for 10 times and sometimes I had to do it from scratch in the end. For example there was no way to describe events system that I have imagined to AI, had to give up after hundreds of prompts. In the end it was still a lot faster then doing it by hand. Once there is concrete pattern to follow it can do the remaining 75% of implementation without a problem.
Damirados
If you have rpi5 check out a demo project for nerves
https://github.com/emerge-elixir/nerves_emerge_demo
You can iterate UI only changes by pasting UI module into IEx shell.
It will require an action that triggers viewport to rerender, for example hitting a + on counter.
That means you can deploy Emerge UI hotfixes using NervesHub on-connect code in production
Damirados
Solve 0.2.0 is out bringing solve oriented flow for handling general messages to controllers with handle_info/2..5
Emerge - 0.2.1 is out bringing initial support for macOS. Aim for this release is to give macOS users to develop nerves apps easily if you wish to develop proper macOS apps that you can distribute through app store you will have to come up with packaging and signing story.
video_targetis also not currently support on macOSIf you want to try it out on mac clone GitHub - emerge-elixir/emerge_demo: Example showcase app built with Emerge and Solve · GitHub and run with
iex -S mixDamirados
Emerge 0.3.1 is out compared to 0.2.1:
Input.sliderSize.min/maxare now proper size resolution combiners. For example now you can have an element withheight(min(content(), fill())attribute and it will be content sized until content becomes bigger than it’s fill portion. TodoApp in demo now uses it for entries so it grows with entries to screen size and then after that entries become scrollable since entries element hasscrollbar_yon it.Next roadmap:
pidand it sends rendered binary to thatpidevery time there is a change.dhedlund
This looks pretty cool. I have also been working on a native GUI framework for elixir and gleam, and ended up with something much closer design-pattern wise to how a lot of elm loops work. So, it’s nice to see a different declarative approach with
solve. For nerves, I ended up going with the idea of a remote renderer that could allow connecting over something like erlang SSH or regular SSH over stdio instead of running natively on the device. Gives some interesting possibilities for non-web server UI as well. Curious if you’re using NIFs or a separate process via ports and what your experience with that has been.My project is called plushie (
plushieandplushie_gleamon hex). It started off with the goal of supporting elixir and gleam for both local and remote desktop apps, but it’s taken on a bit of a life of its own and now supports other languages as well. The main thing I’ve been working on is around the renderer and build tooling to allow for custom rust to get mixed into projects similar to how rustler does things. There might be some things I’ve done as part of all that which could be useful to you in your own endeavors. I’m also not convinced thaticedis the right underlying GUI library and have been considering something else likegpui-component, but there might be some opportunity here to work toward some common underlying renderer that could be shared between our projects.Damirados
Plushie looks interesting. I am not completely sure we can make common underlying renderer on any level higher than
skiawithout making big compromises.On NIF/port qestion currently I use both:
On linux it is Rustler NIF, UI declaration is sent to rust using internal binary format called EMRG and rustler sends messages of resolved events to
pidsetup when starting renderer. If you use it how documentation describes it it will all be setup by viewport.On macOS I had to go for different route. macOS host is standalone rust program that is currently started as a port. macOS requires for main renderer loop to be on main thread. So BEAM now spawns macOS hos as a port and communicates with it through unix socket with yet another small internal binary format. It is archited that way so in the future you can have a macOS host start a beam and give it unix socket to have communication with main renderer loop. That will be needed for properly packaging macOS apps for the store. I think iOS will need similar approach, not sure what are Android limitations.
As I plan to rewrite internals before 1.0.0 (possibly multiple times, as it is a bit of a slopfest now) EMRG binary communication can be another layer to target for plushie but that would require plushie to compromise on
stack,pin,floatingand maybe some other widgets or very awkwardly implement them on top of emerge API. It would require you to implement something like current macOS host for every language. I do plan to add a few more widgets and some kind of canvas API in the future.Currently EMRG is not very well documented or stable currently, there is overview here and elixir serializer here
I am aiming for performance with Emerge and that requires specific UI description model, as relayouting and caching boundaries. Goal is if you strap a touchscreen onto rpi running nerves ui should be as responsive as last flagship phone that had screen of same refresh rate. If you are running desktop app on 500hz gaming monitor there is no reason for ui not to run smoothly on 500fps (currently still fall a bit short on full page re-renders but I have a plan how to improve performance greatly in the future). And there is no reason for standard GUI app to consume more than 50 MB of CPU ram (looking at you electron apps). Lib size is around 6MB(excluding few system dependencies like gpu drivers and native graphics stack for each platform) for now and I will try to keep it from growing.
We can chat more or hop on a call if you want to discuss bit more.
derek-zhou
Theoratically I should be able to render into a VNC server and make remote GUI applications accessible with a standard VNC client, right?