Damirados

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.

https://github.com/emerge-elixir/emerge

https://github.com/emerge-elixir/solve

Showing Posts 1 to 10

Asd

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

Damirados OP

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

derek-zhou

So how much, if anything, is written by AI? 90%+, 5%, or 0%?

Damirados

Damirados OP

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

Damirados OP

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 :upside_down_face:

Damirados

Damirados OP

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_target is also not currently support on macOS

If 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 mix

Damirados

Damirados OP

Emerge 0.3.1 is out compared to 0.2.1:

  • There is initial version of layout caching and renderer cache. Depending on app structure it can bring huge performance improvements especially on animated sections.
  • There is now Input.slider
  • Size.min/max are now proper size resolution combiners. For example now you can have an element with height(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 has scrollbar_y on it.

Next roadmap:

  • Add headless backend, you give it pid and it sends rendered binary to that pid every time there is a change.
  • Make all backends automatically fallback to raster rendering in case there is no gpu.
  • Add option for output pixel format (HDR displays, 1 bit or 2 bit e ink displays)
  • Both of these will be preliminary work for running it on nerves badge/ nerves starter kit. Goal is to have next release run on it :slight_smile:
dhedlund

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 (plushie and plushie_gleam on 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 that iced is the right underlying GUI library and have been considering something else like gpui-component, but there might be some opportunity here to work toward some common underlying renderer that could be shared between our projects.

Damirados

Damirados OP

Plushie looks interesting. I am not completely sure we can make common underlying renderer on any level higher than skia without 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 pid setup 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, floating and 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

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?

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 11030 135
New
shahryarjb
The Chelekom project is a library of Phoenix and LiveView components generated via Mix tasks to fit developer needs seamlessly. One of i...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New

Other Trending Topics Top

mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews