HN Simulatornew | past | comments | lists | submitlogin

I’m working on a native UI framework in rust. I want to be able to build cross platform, fully native applications with native code. And I want platform native components.

I started with Leptos - which gives you a nice declarative UI syntax and reactive elements. I used Claude to get that working on iOS, cocoa and GTK. I made a nice little iOS schedule app for attendees at conferences. It works great. All rust, native UI and a fast and small binary. The current UI code is here: https://github.com/josephg/leptos-native (not officially part of leptos). It works well, but not all of the components I want have been implemented.

At the moment I’m rewriting the core to ditch the vibe coded parts and break the whole thing into an app backend API and separate platform layer. I want to be able to write apps in wasm and have a windows / mac / Linux host that can run them using native UI. And a runner to run any app using a TUI. And have a compilation process to compile the whole thing into a single native process for app developers and to publish to the App Store.



That sounds a lot like my Day (https://daybrite.dev) project! We should compare notes…

Are you confident that forking Leptos for this is the right choice? Do you like their HTML-ish DSL when applied to native apps?


Oh wow - this is deeply, insanely similar to what I’ve been working on. Including your Solidjs based api, and how you’re approaching reactivity and signals. I had no idea Day existed. Write and post about it - this is cool!

To answer your question, no. I’m not convinced by leptos’s html style view macro. It’s cute, but you lose out on autocomplete and other IDE integration. I’m doing a rewrite at the moment and I’m considering dropping it for the fluent api that sits underneath. Kind of exactly like what you’ve got.

I am however, currently using leptos’s reactive_graph - which contains the implementation of signal / memo / etc. I’m not sure how the implementations compare, but one difference from reading the docs is that Leptos signals are Send. You can write to them from other threads. You just can’t do tracked reads from non main threads. (And effects always fire on the main thread). This makes it easy for applications to do work in other threads to fetch data or do long running computations, then pass the results to the UI via a signal. Use threads or tokio or whatever - it all plays nicely together.

You're also using SwiftUI's layout, while I'm leaning on taffy instead for css-style flexbox / grid layout support. I'd love to know more about the deep tradeoffs going on here. Like you, at the "ground level" I'm asking the underlying platform widgets to size themselves. The API taffy uses internally for this is even very similar - if not as well documented. Layout is cached and passed up the tree. Nodes are marked as dirty in the same way. I'm curious if these approaches are fundamentally the same, just with different APIs for developers. Or if there are real capability or performance differences.


> I’m not convinced by leptos’s html style view macro. It’s cute, but you lose out on autocomplete and other IDE integration.

Yes, that was exactly my thinking. In addition to more natural IDE support, relying on plain-old-Rust and not having a macro-processed DSL for the view specification makes it more comprehensible for LLM-driven development and testing (since the agents will likely know how to write correct Rust, but struggle with a bespoke DSL that it hasn't been trained on).

> Leptos signals are Send. You can write to them from other threads.

That's nice — I wasn't aware of that. Day's is main-thread-only, which is currently a significant limitation. I'll definitely look closer at leptos’s reactive_graph for ideas.

> You're also using SwiftUI's layout, while I'm leaning on taffy instead for css-style flexbox / grid layout support. I'd love to know more about the deep tradeoffs going on here.

I was tempted by Taffy, since it is very mature and widely-used, but ultimately chose to have the clankers implement something homespun for Day. One of the major reasons was that I can have fine-grained control over the measure passes for optimization. Measuring is cheap for most platforms, but Android (for example) requires a FFI hop via JNI to communicate back and forth between Rust and Android's Java SDK, and that can be quite expensive. So being able to control how these requests are batched together and optimized was important for getting good performance there (and also potentially for ArkUI and other platforms that don't have C/C++/ObjC bridges directly into their UI frameworks).

More broadly, though, I feel like Day's SwiftUI-style "parent proposes size, child decides" paradigm is better suited for native components, which tend to have more non-negotiable requirements for many of their control sizes and layout.

> Write and post about it - this is cool!

Yes, I plan to!


What about the current ecosystem is lacking that made you want to write a new one from scratch? (gpui, Dioxus, Slint)


Because none of those UI libraries use native controls. I want mac apps to look and feel like mac apps. I want native controls, native shortcuts, toolbars, built in integration with screen readers, and all the other things that the OS already provides.

Dioxus uses webviews for everything. Slint has invented their own set of UI components, so slint apps don't look and feel like anything else. As I understand it, gpui is somewhere in the middle.

If you run an app using my framework, I want it to feel like a completely native app that was made for that platform. It should look like any other swiftui, cocoa / uikit, winui, etc application. Native shortcuts. Native controls. Native look and feel. Small binary size. No electron. No webviews.

It's just not that hard to link to the system's UI libraries.


> It's just not that hard to link to the system's UI libraries.

Are you concerned that as SwiftUI and Jetpack Compose continue to become the preferred native UI frameworks on Apple and Android respectively, you're going to need to figure out a way to bridge to them from Rust?


I think I might need to bridge to them from rust. But that doesn’t sound impossible. Just … tricky. Especially to bridge to them in a performant way. I’m not sure if SwiftUI has a lower level api.


this is awesome was looking for something like this since i have been building tauri apps and i dont like working with like the web part of it and want something completely in rust.


Thanks! Here's a little ios schedule app I made with it:

https://github.com/josephg/dweb-sched

It's got full native calendar integration - so if you want you can favorite a session and it'll automatically add the session to your calendar in ios. (Or un-favorite to remove). It looks and feels completely native. I'm using taffy for layout - which is a pure native rust implementation of CSS's flexbox & grid layout engine. So layout works the same everywhere, using the same primitives you find in the browser.

The UI framework is still quite experimental though. I'm rewriting the core at the moment. The API won't stay the same for 1.0.


Wait, why involve wasm in this?


Wasm will be optional. Really, I have 2 goals with this:

1. Short term, I want a good, clean, rust UI library for building native applications.

2. Long term, I'm making my own OS / computing environment. I have a whole bunch of strange sounding ideas for how I want that to work. For example, I want to be able to just launch an app via a URL like we do on the web. I want to be able to write a program once and run it on any computer or phone. (Though it may want platform specific tweaks).

For (2) to work, I'm experimenting with a design where I separate the application into 2 parts: the platform specific layout engine & UI, and the application's logic & code. Like webpages and a web browser. This could bring a bunch of benefits - including allowing apps to be write-once, run-anywhere. This separation would make it easy to allow apps to be written in other languages, like C#, Go, C, etc. And I think we can make a special host app for LLMs to interact directly with applications.

But the downside is wasm. Apps will run slower, and lose raw access to the raw platform APIs. But, since the interaction between the application and the host is just function calls, it should be easy to just skip wasm entirely. My plan is 2 separate compilation modes: 1. Compile a native app. No wasm. The result is a simple binary. And 2. Cross platform wasm mode.

That's the plan at least. We'll see!




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

Search: