5 ms·
Show HN: Shirei, cross-platform GUI framework in native Go
- swiftcoder 3mo ago> Experience has shown us that an immediate mode API is the only sane way to program GUI applications I wonder how long till they pivot away from this belief. I feel like everyone in UI goes through this phase as some point, but in the end it doesn't scale to truly complicated UI
- hsn915 3mo agoIt's the only thing that can scale to complicated UI
- gen2brain 3mo agoWhat does "scale"even mean in UI context? 10 or 100 controls in app makes difference how exactly? Retained apps redraw when needed, they are idle most of the times. How redrawing every frame helps to scale?
- well_ackshually 3mo agoThis thread (and post) keeps mistaking immediate mode GUIs with declarative UIs. You can have declarative UIs that aren't immediate: the vast majority of them are, and they are idle most of the time.
- hsn915 3mo agoDoes "immediate mode" mean the UI refreshes at a constant 60fps rate like a video game, redrawing everything all the time? No. It means that you build the UI by describing what it should look like now, based on the data / state you own, without referencing any existing "widget" object or trying to manipulate it. Scale is not about the number of buttons, but the structure of the data. You have a list of objects, within each objects you have several fields, some of them lists, some of them maps. within some of those sub-items you have other lists and maps, nested arbitrarily. This would be hell to manage for a retained mode UI. You have to mirror the application data into a widget tree and keep all the elements in sync, all the way down to the arbitrary depths of it. You'd be writing thousands of lines of code that do nothing but keep your data in sync with widget states. You'd have many one off bugs where one sub field fails to sync in some scenarios. Your only options is to be more defensive: more events, more full-resync. As a result, the codebase is complicated and the application feels slow/heavy, because updating widget states is costly. In immediate mode, none of that matters. You don't have a parallel widget tree.
- swiftcoder 3mo ago> In immediate mode, none of that matters. You don't have a parallel widget tree. No, instead, you need to have your entire dataset in memory, and potentially rebuild your whole tree on every update. This causes quite a lot of problems for out-of-core datasets - you end up needing to maintain proxies for things like items in scrollable lists that aren't loaded into memory yet.
- hsn915 3mo ago> you need to have your entire dataset in memory Are we talking about displaying tables with billions of entries? I'd like you to show me how retained mode gui scales well with that use case.
- cosmic_cheese 3mo agoYeah. Based on my personal experience I think some kind of hybrid of old-school imperative retained and declarative retained, both with granular reactivity is probably the correct balance for "serious" high-utility desktop applications. Declarative approaches are great for smaller components but become a nightmare for anything much more complex than a relatively simple mobile app while imperative requires a lot of extra legwork at the component level, and as I understand (which may be incorrect) immediate mode makes certain types of optimization more difficult.
- lioeters 3mo agoIn my experience, it's the opposite. Immediate mode GUI, or at least a functional and declarative approach, is the only way I've seen it scale well. It's more modular and scale-independent. On the other hand, retained mode, or imperative/OOP approach to state management, becomes complicated and monstrous quickly; it's the dominant style and can be made to work OK, but typically hellish to maintain or develop beyond a certain scale. Admittedly I'm simplifying too much and conflating paradigms. My preference is something like "functional core, imperative shell" or maybe "immediate-mode core, retained-mode shell" if that makes sense.
- deleted 3mo ago[deleted]
- rootlocus 3mo agoIs Tracy complicated enough? Because it's imgui. https://github.com/wolfpld/tracy https://github.com/wolfpld/tracy
- timhh 3mo agoThat looks quite simple. Think about something like this, a commercial SystemVerilog simulator (this only shows a fraction of the UI). https://blog.reds.ch/wp-content/uploads/2018/09/questa13.png https://blog.reds.ch/wp-content/uploads/2018/09/questa13.png Or something like Visual Studio. Obviously most GUIs are not nearly that complex so immediate mode can get you quite far. Its biggest limitation is that it makes it hard to do some layouts. Your GUI layout becomes dictated by your data dependencies which is quite awkward.
- well_ackshually 3mo agoAbsolutely zero difficulty redoing this in a react style renderer. The only complexity is being careful with your data dependencies so as to not needlessly rerender. Each pane is easily isolated, can share data with a view model scoped properly, etc. Writing it in an imperative toolkit is a "oops I forgot to update my data here" kind of hell. Data binding makes it slightly less worse
- swiftcoder 3mo ago> Absolutely zero difficulty redoing this in a react style renderer I would not classify a react style renderer as "immediate mode". It has aesthetic similarities with IM GUIs, but ultimately there is a fully retained tree under the hood, that gets diffed/mutated on every update
- TazeTSchnitzel 3mo agoI will admit that I don't like vibecoded things, but perhaps I must stomach that AI will be writing a lot in this brave new era. However, when the commit history has stuff like v0.5.0: native backends, software renderer, text input, IME Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Codex <codex@openai.com> Co-authored-by: Composer <composer@cursor.com> Co-authored-by: Cursor Grok 4.5 <noreply@cursor.com> 377 files changed Lines changed: 62423 additions & 2871 deletions it's very hard. These “change the entire world” commits make for a history that is impractical to follow for a human, and therefore of little interest to me.
- hsn915 3mo agoThis is a publish-only mirror repo. The commit history is the publish history, not the work history.
- weare138 3mo agoWhere's the actual repo then?
- lietuvis 3mo agoI'm assuming you're the author, why not publish everything?
- em-bee 3mo agothat doesn't make much sense. why go out of your way to publish a selected history instead of the whole work?
- hsn915 3mo agoI have several projects in the same git repository which also forms a workspace in Go. Many of the projects in that repo are not public.
- em-bee 3mo agook, so because of that you manually export changes you want to publish to a new repo? i'd start separating the repos. personally i would be uncomfortable using a repo that the developer does not use for their own development. if you ever want to accept contributions this might become an issue. but that's just my feeling.
- iafan 3mo agoI understand the core is the layout engine and a component library? Does the rendering somehow benefit from GPU? I recently had a good experience creating custom UI based on ebitengine — also a cross-platform Go engine. As it is a game engine, it has this built in game drawing loop, GPU-accelerated, with some cross-platform kb/mouse input handling. And this feels like a good platform to build the layout engine and components on top of. Have you ever considered this? Or how does your approach compare to that of ebitengine? Did you try (and do you position) your library to build custom UI for some underpowered computers such as Raspberry Pi?
- hsn915 3mo agoShirei does not use GPU for rendering. It's fully software rendered. > ebitengine I have considered using it as a backend, but the blocker for me was how it handles resizing: the window content will stretch while it's being resized.
- roncesvalles 3mo agoWails is another cross-platform GUI framework in Go: https://wails.io/ https://wails.io/
- thisislife2 3mo agoWails is more like Tauri (Rust) - https://tauri.app/ https://tauri.app/ - both use a WebView to render the frontend.
- ahriad 3mo agoHow it compares to Fyne?
- 5701652400 3mo agocross-platform is overstatement. can I run it on Android? iOS? no? then 99.999999% of real world users cannot access it. and if it is desktop oly, what is the point? it is no better than web.
- cosmic_cheese 3mo agoThe needs of desktop and mobile are different enough that it's extremely difficult to build a UI framework for both that doesn't seriously compromise one paradigm or the other. I would argue it's one of the main reasons why frameworks like Flutter stuggle with widespread adoption on desktop — it was conceived primarily as mobile-oriented, and so on desktop you're stuck with half-baked third party components for essentials such as datagrids and tree views. WinUI with its mobile heritage in UWP suffers similar problems. GTK + Adwaita tries to straddle the fence and produces a subpar experience on both sides. Desktop data density is terrible due to mobile-minded button sizes and margins (big touch targets, bloated whitespace to make inadvertant touch interactions less frequent) and desktop-oriented widgets like tree views feel out of place on mobile.
- 5701652400 3mo agoso it is not cross-platform? or all available platforms are... desktop. serious vibes of shortcuts and avoiding real hard work that brings real value.
- comex 3mo agoIt is still meaningfully cross-platform to support all 3 major desktop platforms rather than just one.
- DANmode 3mo agoWeb is fantastic.
- hsn915 3mo agoIf desktop only is so useless, why are so many people create TUI apps?
- oooyay 3mo ago> Immediate mode API in the true sense: you never need to maintain UI widgets or sync your data with widget state. https://judi.systems/shirei/ https://judi.systems/shirei/ Known Issues & Limitations The following are known issues and limitations that we plan to tackle: Large text blocks will kill responsiveness! Use the LargeText widget. The widget catalog is aimed at developer tooling, not general consumer polish: no rich text, tree widget, or date picker yet. There is no robust theming system. Some widgets take an accent color; custom button styles mean implementing your own (the stock Button is a usable reference). Styling can still be verbose at times. Are these statements compatible?
- nickcw 3mo agoI had a look through the code to see how it manages not to use a pile of C libraries with cgo like other Go GUI libraries. The answer is platform dependent: Windows loads the relevant DLLs by hand and calls them. This is a well established technique in Go programs and due to the super stable DLL interface works well. Linux has an x11 and Wayland backends and these implement (through a library) the wire protocols directly in Go which is nice and will make cross compilation and distribution easy. macOS does appear to use cgo to access the cocoa libraries. macOS doesn't like statically linked Go programs anyway though as they don't use system name resolution so this isn't a bad compromise, but will mean macOS stuff needs to be built on macOS I think. I didn't see Android or iOS support. A nice innovative approach to GUI building. Since the lowest common denominator for the backends is an RGBA buffer, this will bypass all accessibility things the OS provides. The above gleaned after a few minutes reading the source so may not be 100% accurate.
- irq-1 3mo ago> Mobile is under consideration (no decision yet). If it is supported, it will be limited to utility-style apps — not games or rich multi-touch experiences. https://judi.systems/shirei/ https://judi.systems/shirei/ No Multiple Windows so even desktop apps will be limited to "utility-style apps". I compiled and ran the process_monitor example on linux: it works, compiles fast and is about 10mb. Also cross-built for windows and it's 8.4mb. Can't build for macos/arm64 (Under wine the windows exe doesn't render text. weird.)
- irq-1 3mo agoexamples/process_monitor$ GOOS=darwin GOARCH=arm64 go build # go.hasen.dev/shirei/cocoabackend ../../../gopath/pkg/mod/go.hasen.dev/shirei@v0.5.0/cocoabackend/ perf_darwin.go:198:11: undefined: softRenderer ../../../gopath/pkg/mod/go.hasen.dev/shirei@v0.5.0/cocoabackend/ perf_darwin.go:208:22: undefined: softRenderer
- hsn915 3mo agoYou need to have some fonts installed. I think for some reason a bare wine setup either has none, or has fonts that Shirei cannot recognize.
- shinzui 3mo agoWhat a waste of tokens.
- 5701652400 3mo agotrue to that. looks like AI took shortcuts and avoided real work and real hard problems. might as well just flip a random bits for cpu hours.
- Reubend 3mo ago> What is it that matters for "immediate mode"? Is it that the UI renders everything every frame? No. It's that you build the UI by describing what it should look like everyframe, based only (or mostly) on the data. This is why React won... I don't think that's why React got so popular. React popularized unidirectional data flow, which is different than immediate mode rendering. This readme file seems to conflate the two of those. Now that I think of it, couldn't one argue that React itself is a retained mode UI, since it choses which components to re-render and which not to?
- lietuvis 3mo agoSuper vibe coded project still uses an LRU cache (github.com/dboslee/lru v0.0.1) as a dependency, this is exactly the things these llms were supposed to solve right, why the hell do people still add these 100 lines dependencies in their projects?
- tptacek 3mo agoThis looks better than the other native Go GUI frameworks. Frameworks like these are a really good target for coding agents: the biggest impediment to building a new UI framework is the sheer amount of meticulous grunt work needed. So, sure, I'm on board with the idea of languages not normally a perfect fit for native UI work getting solid, generated frameworks. But: what's the real advantage at this point to having frameworks like these? I can get arbitrary SwiftUI interfaces built very quickly, with a lot of attention to macOS (for instance) idiom, and an automatically generated interface between the SwiftUI app and Go. That works pretty great. Why take the UX hit at all?
- hsn915 3mo agoI think AIs generally "like" the API surface exposed by Shirei. They seem to understand it pretty well and are able to "vibe code" any kind of UI you ask of them using this framework. To your general point though, yes, there's a lot of uncertainty about what things it makes sense to build in the AI era. I don't have good answers for what would make sense for 10 years down the road, but at this point of time, I think a project like this actually makes perfect sense. Now that AI can write the code for us, we need better frameworks and libraries, because a lot of what we have now is quite honestly slop. You could say that you could get AI to maintain 3 separate codebases of the same application UI, each one targeted to a different platform, and the AI will maintain the feature parity and you won't have to worry about it. For now, AI can take care of coding, but it does not relieve you of having to pay attention to things. If you create 2 or 3 code bases for the different platforms you target, the maintenance burden still falls on you. But I don't know for how long the situation will remain like this. Last year I did not think I'd be using AI for coding. I dug up a few tweets I posted last year saying that LLMs have hit a plateau and will stop improving, and that AI coding is a scam being promoted by charlatans.
- rootlocus 3mo agoCo-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Codex <codex@openai.com> Co-authored-by: Composer <composer@cursor.com> Co-authored-by: Cursor Grok 4.5 <noreply@cursor.com> How do you get so many agents to co-author a single commit?
- kvnhn 3mo agoRebase (squash), I assume