R
Raph Levien
raphlinus.github.io · Personal blog · on HN since 2018
Raph Levien, a software engineer working on Rust GUI toolkits and graphics, writes about UI architecture, color spaces, and curves.
What HN saysHN commenters recommend it for Xilem's architecture, Rust GUI design, and Euler spirals, and cite his work on Druid when comparing GUI libraries.
128HN people shared it
82linked it in comments
89stories submitted
7.7Kstory points
5 months agolast shared
2018people per year2026
Most-shared posts
- 1Xi-Editor Retrospective16 people · 538 points · first shared 2020 · 157 comments on HN
- 2Towards a unified theory of reactive UI11 people · 213 points · first shared 2019 · 35 comments on HN
- 3An interactive review of the Oklab perceptual color space9 people · 124 points · first shared 2021 · 33 comments on HN
- 4With Undefined Behavior, Anything Is Possible8 people · 94 points · first shared 2018 · 28 comments on HN
- 5Xilem: An Architecture for UI in Rust7 people · 461 points · first shared 2022 · 103 comments on HN
- 6Advice for the next dozen Rust GUIs7 people · 348 points · first shared 2022 · 270 comments on HN
- 7Towards Principled Reactive UI7 people · 236 points · first shared 2020 · 97 comments on HN
- 8Rust 2020: GUI and Community7 people · 226 points · first shared 2019 · 71 comments on HN
- 9Homepage7 people · first shared 2020
- 10Rust 2021: GUI6 people · 372 points · first shared 2020 · 244 comments on HN
- 11The stack monoid revisited6 people · 249 points · first shared 2021 · 28 comments on HN
- 12The Stack Monoid5 people · 195 points · first shared 2020 · 47 comments on HN
- 13The Smooth Resize Test5 people · 12 points · first shared 2019 · discussion on HN
- 14Thoughts on Rust bloat4 people · 558 points · first shared 2019 · 305 comments on HN
- 15Show HN: 2D Graphics on Modern GPU4 people · 484 points · first shared 2019 · 87 comments on HN
What HN people wrote when they linked it
nicoburns · 2020-11-01
Iced https://github.com/hecrj/iced and Druid https://github.com/linebender/druid
Iced is taking the "get something working now" approach, whereas Druid is taking the longer term "build it right" approach. I wouldn't recommend either of them for serious projects yet though.
I would also recommend Raph Levien's blog https://raphlinus.github.io/.
ilirium · 2025-02-16
Some time ago I did research for myself on the topic of GUI libraries/frameworks. Below are some things from this study. The modern tendency for all frameworks to use 2D rendering engines to draw all widgets from scratch instead of using platforms' widgets and APIs. Usually, they use Skia.
I can recommend reading blog posts by Raph Levien [1], who is one of the founders of Linebender [2] and Xilem [3]. Xilem is a Rust cross-platform GUI framework intended to use GPU for rendering in the first place. Earlier, they tried to develop their own GPU meta-API, then they switched to WGPU [4] and developed their own 2D rendering engine instead of using "standard" Skia, like many others.
JetBrains develops Compose Multiplatform [5]: using the same Android API - Jetpack Compose, but for many platforms and in Kotlin. They also use Skia but are considering switching to Impeller (a new 2D rendering engine in Flutter) because of performance issues in Skia with shaders compiling.
Slint [6], was founded by 3 guys who's been working for a long time in Qt Group. It is written in Rust but uses DSL to develop GUI. As I understand, they try to solve the main fundamental issues in Qt.
MAUI, as I understand it, was Xamarin.Forms and now Microsoft tries to develop it.
Another interesting thing. There is a part of each GUI framework, a system to automatically place widgets on the screen - layouting, something like a grid, table, and so on. Several years ago, Apple had a big boom in the…
raphlinus · 2020-11-04
Thanks for the kind words. My thinking has evolved since that video; my blog at https://raphlinus.github.io/ is a good place to check.
As flohofwoe suggests in a sibling, combining an imgui-like API with an actual retained widget tree would be something of the best of both worlds. That is indeed pretty close to what the Crochet prototype does. We're not trying to exactly match the imgui but it's pretty close. In particular, getting actions back from widgets (like button presses) is the return value from calling the widget-creating function. That's a notable difference from, say, Jetpack Compose, which is fairly imgui-like on widget creation but pretty much uses callbacks for those actions. Crochet does solve the page tearing problem (though the current implementation is hacky, don't look too closely under the hood).
Another note - the Dear ImGui implementation has become a lot more sophisticated over the years, and is no longer a simplistic implementation of the immediate mode GUI concept. It has unique id's for widgets, its text processing has become better, etc.
Levitating · 2026-04-08
If you want to learn more about Xilem's architecture I recommend the Raph Levien's blogpost: https://raphlinus.github.io/rust/gui/2022/05/07/ui-architecture.html
masfuerte · 2026-02-09
You might be familiar with these, but GP wrote a couple of excellent references on Euler spirals:
https://raphlinus.github.io/curves/2021/02/19/parallel-curves.html
https://levien.com/phd/euler_hist.pdf
Lichtso · 2025-10-18
Yep, stroking is just filling of the space between offset curves (aka. parallel curves), and that "slightly scaled down version of the first" is the "calculate an offset curve explicitly" approach I mentioned.
Though it is very unpractical because the offset curve of a cubic bezier curve is not a cubic bezier curve anymore, instead it is an analytic curve of degree 10. Thus, in practice the offset curves for stroking are either approximated by polygons or implicitly sampled from signed distance fields.
Raph Levien has a good blog post about it:
https://raphlinus.github.io/curves/2022/09/09/parallel-beziers.html
One more thing: Offset curves are different form classical scaling from a center point in all but the most trivial cases where there exists such a center; namely regular polygons. And cubic bezier curves can be concave, even have a self intersecting loop or form a cusp.
mananaysiempre · 2025-01-26
To have a compositor not introduce a frame of latency more or less requires it to race the beam, which has definitely been suggested[1], but you can see how it’d be difficult, and so far no operating systems have tried as far as I know. And as for good frame pacing support in UI toolkits (and not just game engines), well, one can dream. Until both of these are in place, 2.5±0.5 seems to be the hard limit, the question here is more where the Mutter is losing another frame (which even the greats tell us[2] is not hard to do by accident).
[1] https://raphlinus.github.io/ui/graphics/2020/09/13/compositor-is-evil.…
[2] http://number-none.com/blow/john_carmack_on_inlined_code.html
bbkane · 2023-02-04
This is a strange take for me- people are CONSTANTLY trying to find new, better ways to do UI. Elm, React, DearIMGUI, Flutter, and Xilem are some of the more well-known fairly recent libraries.
See https://raphlinus.github.io/rust/gui/2022/07/15/next-dozen-guis.html for an overview of UI libs in Rust.
See https://www.cmyr.net/blog/gui-framework-ingredients.html for a great overview of some of the challenges making a GUI library
chrismorgan · 2022-10-11
Good reading on this issue: https://raphlinus.github.io/rust/gui/2019/06/21/smooth-resize-test.htm…
danielvaughn · 2022-10-03
Despite being a noob in this space, I'm very interested in it. Have you come across Ralph Linus? I've seen him pop up in a few HN threads that discuss SVG rendering with the GPU, and he's doing some interesting things: https://raphlinus.github.io/
singhrac · 2022-06-04
Another one if you enjoy this sort of thing like me is Raph Levien's work on the stack monoid; this [1] blog post and this [2] ArXiV paper are great places to look.
[1]: https://raphlinus.github.io/gpu/2020/09/05/stack-monoid.html
[2]: https://arxiv.org/abs/2205.11659
eliasnaur · 2022-03-26
With intelligent frame pacing you can sacrifice, say, a frame of input latency to sustain high frame rates. See https://raphlinus.github.io/ui/graphics/gpu/2021/10/22/swapchain-frame…
> Are immediate-mode GUIs up to the task? What is driving their authors to pursue this design? Why aren't they choosing a declarative design
Immediate mode UIs make managing state much easier, and avoids callbacks for event processing. That alone is worth it in my opinion.
neolog · 2021-04-06
I saw your webpage on programming language choice, but I couldn't figure out how to use the comment box. So here's my comment.
Rust seems like a good candidate. The runebender/druid/xi project has an active chatroom [1] full of people [2,3,...] with deep expertise in typesetting, text rendering, etc.
[1] https://xi.zulipchat.com/
[2] https://raphlinus.github.io/
[3] https://joy.recurse.com/~cmyr
chris_wot · 2021-04-06
This is excellent, but I also recommend the following that describes how text is laid out of the screen:
https://raphlinus.github.io/text/2020/10/26/text-layout.html
qwe098cube · 2020-05-15
https://areweguiyet.com/ gives a broad overview, but is slightly outdated i believe. I recommend all raph linus' research on this topic, fairly recent blog: https://raphlinus.github.io/rust/druid/2019/10/31/rust-2020.html
Personally I used iced [1] a bit and found it very pleasant to use. iced is cross platform, sponsored and very active.
https://github.com/hecrj/iced
robocat · 2019-07-15
Right. When you are talking about the compiler and the abstract machine, perhaps some sentences could be clearer about that (e.g. the sentences I latched onto - which I admit is my fault for skim reading).
Responding to whether C is "low-level" I like this comment: http://lambda-the-ultimate.org/node/5534#comment-95721 And processors have undefined behaviour so should we say assembly is not "low-level"? e.g. "Grep through the ARM architecture reference manual for 'UNPREDICTABLE' (helpfully typeset in all caps), for example…" - pcwalton
Thanks heaps for your article which was a good read, and it led me to the funnier side of undefined behaviour: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-beha… and https://lkml.org/lkml/2018/6/5/769
steveklabnik · 2019-03-17
https://raphlinus.github.io/personal/2018/05/08/ecs-ui.html is an entry point into the main alternative that’s being explored, see “druid” as a package that’s an implementation of (an evolution of) these ideas, though it’s still early days.
In general, Rust hates big balls of intertwined mutable state. And traditional OOP-y UI frameworks are basically giant balls of intertwined mutable state. You can do it, but it’s not great. We’ll see.
lioeters · 2026-06-14
This is an excellent comment. Then I realized you're the same person who wrote the article I currently have open in the next tab. Advice for the next dozen Rust GUIs - https://raphlinus.github.io/rust/gui/2022/07/15/next-dozen-guis.html
Insightful point about how the struggle to converge on a well-designed UI paradigm is related to a larger question of how the industry is still experimenting and exploring the problem space, particularly:
> reactivity, which is at heart incremental computation
Another comment that caught my attention up-thread was talking about "incremental lambda calculus", which is the same question in different words. My impression was that ideally it needs a language-level solution to be able to support "diff" and "patch" not only on the data but the running code, perhaps built from primitives like continuations.
> feels to me a bit like async
Maybe part of the difficulty with reactive UI is fundamentally related to how the language "solves" async, for which there's still no real concensus on the best way to solve it.
quag · 2025-08-29
It sounds like you've got something specific in mind when you say, "modeling". The term modeling is used in a lot of different situations to mean different things. For example, it could mean to make a 3d model in Blender, it could mean to pose for someone to paint you or to take a photo, with databases it's used to mean modeling the data, with statistics it's used to mean finding a way to simply represent and reason about the data (create a model of it).
The things you've listed out make me guess you want to write 2d or 3d image rendering software. Is that right?
If that's the case, there's no substitute for trying to recreate certain algorithms or curves using a language or tool that you're comfortable with. It'll help you build an intuition about how the mathematical object behaves and what problems it solves (and doesn't). All of these approaches were created to solve problems, understanding the theory of it doesn't quite get you there. If you don't have a good place to try out functions, I recommend https://thebookofshaders.com/05/ , https://www.desmos.com/calculator , or https://www.geogebra.org/calculator .
A good place to start is linear interpolation (lerp). It seems dead simple, but it's used extensively to blend two things together (say positions or colors) and the other things you listed are mostly fancier things built on top of linear interpolation.
https://en.wikipedia.org/wiki/Linear_interpolation
For bezier curves and surfaces here are some links I've…
celeritascelery · 2023-06-22
I found the discussion on extensibility vs composability to be really fascinating. The author is right that extensibility gives you less freedom between tools. You can't take magit to vim or helix, because it is an Emacs extension. And each tool has it's own way of extending it, which means you need to learn essentially a new API (if not an entire language) to extend a tool.
However extensibility makes it much easier to move within a tool. The authors sample kakoune config for doing splits is a great example. Since Kak doesn't support splits natively, you have to learn 3 separate tools do the spliting in a WM. In something like Emacs there is only one thing to learn to manage splits on all platforms. And it is using the same extension mechanisms you use for everything else.
I found this the paragraph just before the conclusion to kind of an interesting demonstration of these trade-offs:
> All of that to say that, the take of Helix is pretty good here, because all of those UNIX problems are not there in that editor: everything runs in the same process, inside the same memory region.
The author spends a lot of time praising composability over extensibility, but then admits that Helix has some real advantages because it is not composed with tree-sitter or lsp, it has those built in. Essentially it was extended with those features, they become part of editor, instead of trying to interacte with them in a uniform way.
This reminded me of the xi-retrospective section[1] on…
vlovich123 · 2023-04-03
Nope no ChatGPT.
You may want to reread what I said. I was responding to someone talking about games and game performance in the context of text rendering. And the PhD research topic is how to use the GPU to accelerate text rendering.
You seem to perhaps be misunderstanding what I’m saying and somehow thinking I’m defending
> Microsoft Teams takes 9 seconds to display under a kilobyte of text, including 3 seconds to just display a splash screen)
I’m not. Clearly it shouldn’t take that long to render that text. But achieving a screen full of text at 120fps (or is it even just 60fps) on the highest resolution displays is actually a difficult problem for CPU renderers to achieve (even for the greatly simplified case of a single mono space font). If you think otherwise, you may want to sync up with Raph and publish your contributions to this space. It’s possible I’m getting some of the specific details wrong (again - not my area of expertise) but there’s definitely a push to find HW acceleration within the GPU to achieve those frame rates (and not just text rendering - all 2D rendering is difficult to HW accelerate).
Notice in [3] how CPU renderers are still lower latency than GPU ones because it’s an area of active research that hasn’t yielded winners yet.
Also I’m well aware we have super computers in our pocket. But don’t forget that the screen resolution is really frickin high and DPI scaling on top (so that text is actually legible) adds additional overheads (+…
duped · 2022-08-03
I think architecture specific stuff is at best tedious and at worst boring - the general practice is: given some embarrassingly parallel algorithm, implement with the architecture-specific operations. google, read manuals, benchmark, and find out if your implementation is better/worse than sequential evaluation. You generally need the sequential fallback if the size of the input data set is not an integer multiple of the target SIMD lane width which is (usually) fixed and smaller than your data set. If it's bigger you just pad with garbage and move on with your life.
The more interesting problem is converting from non-embarrassingly (impressively?) parallel algorithm to an embarrassing one.
For that there are some standard tricks. Most are based on some theory. The first and very effective one is based on some abstract algebra: given a set of values A, define an operation * that is associative (for x,y in A, x * y = y * x) and commutative ((x * y) * z = x * (y * z)). Then define some unit value in A such that u * x == x. The existence of a binary associative operator and unit value is called a "monoid"
If your algorithm can be formulated as follows :
y[0] = x[0]
y[1] = x[0] * x[1]
y[2] = x[0] * x[1] * x[2]
...
y[N-1] = x[0] * ...* x[N-1]
Then you can recognize this as prefix sum (1) and convert to SIMD over N lanes using any of the standard decompositions. This is based on exploiting the algebraic properties of the operation * to reorder instances.…
anonymoushn · 2022-06-21
> Where are you getting those numbers? I think situation is much more complicated, than your give it credit.
I explained this upthread.
Glibc apparently supports 4 distinct subsets of extensions for x64 according to this article about them removing a 5th one: https://www.phoronix.com/scan.php?page=news_item&px=Glibc-Dropping…
Most code isn't glibc and would be fine supporting just 2 distinct subsets of SIMD extensions for x64.
> See https://raphlinus.github.io/rust/simd/2018/10/19/fearless-simd.html
I haven't looked into these Rust SIMD libraries much, but it sounds like they are doing worthwhile things. In 2022 you can also use Google's Highway if you are able to integrate template spaghetti into your code, but it's understandable if one cannot do this.
> It's still dropping down to assembly and having to worry about arcane details like endianess and byte alignment.
You don't have to write assembly. In Zig, you can just use binary and unary operators on vectors and get new vectors without using any intrinsics, but you'll still need to use more than 0 intrinsics for string parsing because you probably want pshufb. In the case of pshufb specifically, and this is representative of most of this stuff, the entirety of the complexity that you pay for having one AVX2 target and one SSE4.1 target is that the SSE4.1 target needs to get by with a half-as-wide pshufb. One way to do that (which might not be the best for all uses of pshufb on the SSE4.1 target) would…
rektide · 2022-05-07
Author Raphlinus has an incredible history of great, superb technical posts here, many which have spawned great discussions[1].
Referenced in this article are: Xi-Editor, discussed in Xi-Editor Retrospective[2] and Druid, discussed in Rust 2021: GUI[3], which follows closely after Principled Reactive UI[4] (describing a prototype for Druid called Crochet).
> I have long believed that it is possible to find an architecture for UI well suited to implementation in Rust, but my previous attempts (including the current Druid architecture) have all been flawed.
These have all been very very good & technical posts on what toolkits really support & enable ui (amid other great technical topics too). It's delightful seeing such an ongoing continuation, an evolcing refinememt of ideas & self-review from someone of such expert caliber.
Rarely do we get such an intimate view into what the real hunt for rightness is, see how we ever hunt for perfection. Personally I believe that hunt for better is one of the undertold aspects of hackerdom, a less visible less knowable reciprocal to fast-and-dirty. Tapping & enabling this creative, knowledge & intellect based capability is a core spring from where greatness emerges.
> I have studied a range of other Rust UI projects and don’t feel that any of those have suitable architecture either.
It's also notable how widely raphlinus travels to get the best persepctive available. This post begins with a a vast field survey of other ui libraries &…
bmer · 2021-02-19
Hi Raph! This was a fun read, and I have some questions to help me contextualize this post with respect to your other work.
* In terms of mathematical technique, this is a "sister post" to https://raphlinus.github.io/graphics/curves/2019/12/23/flatten-quadbez… , because they both use the idea of using the relationship between arclength and curvature to determine how best approximate one type of curve as another curve?
* Have you done the analysis in this paper with a Euler spirals -> cubic Beziers because they are the "cultural norm", or because quadratic Beziers are problematic here for some reason?
* When you say that you look forward to exploring using Euler spirals for other "classical 2D geometry problems", do you mean "classical 2D geometry problems, related to 2D graphics rendering", or are you actually thinking more generally? If you're thinking in terms of 2D graphics rendering, do you have a short-list of problems in mind?
* Here's an idea for a book. On the cover, a thousand cartoon Raphs are pictured, each equipped with a typewriter. The title is: "1000 problems your 2D graphics renderer NEEDS to handle (no solutions included)". Do-able for 2021?
bluejekyll · 2020-01-20
To be clear before I respond, I believe there were some overzealous individuals that were concerned about unsafe usage in the project and did a very poor job of communicating with the maintainer. This follow up post drives at the heart of that: https://raphlinus.github.io/rust/2020/01/18/soundness-pledge.html
Now to your question. Rust is a language that allows you to express correct programs in a number of contexts. Memory safety and concurrent modification free code being two chief ones. What people are constantly proving is that unsafe escape hatches for performance reasons are not as regularly required as similar C implementations would make you believe.
In games and HFT, I would argue having correct programs is as important as any other area of development. That’s the gamble, that you no longer need to make the trade off of safety vs. correctness. But, for expediency of development I could understand why folks see this as a trade off that is required, but that’s really just about the maturity of the language ecosystem in those areas.
Ideally any unsafe code will be contained inside a crate and never be exposed to users of that crate. The crate says “I’m giving you these safe APIs and if you use them, then your code will be safe”, it’s a contract. The point being, for games and HFT, there are many cases where you’re interacting with hardware to improve performance, the big question then becomes, can those hardware abstractions offer safe APIs such that any code built…
valand · 2019-12-10
Having your PR rejected in a healthy environment means that your PR is radically far from the reviewer's expectation.
Having your PR rejected in a toxic environment can mean a lot of things, and a company sought after doesn't mean that it MUST be not toxic.
First, you have to make sure if both of YOU and YOU ENVIRONMENT is healthy. If both are healthy, proceed reading.
> The challenge here is to deliver good quality code, while maintaining a decent speed of delivery.
You made it sound like producing good quality code = slowness. FALSE. Seeming slow, good quality code boosts your team's velocity. BUT keep in mind: "quality" is "the standard of something as measured against other things of a similar kind; the degree of excellence of something". Your team has its standards, either is a derivative of other globally acknowledged standards such as https://blog.golang.org/go-fmt-your-code, https://github.com/microsoft/TypeScript/wiki/Coding-guidelines, https://twitter.com/dan_abramov, etc, or self-made standards. You go follow them, make them happy!
Coding and design skill has a different definition than code quality. It is what punches up to the sky: the overall velocity, the success of the team, the balance of growth and culture retainment of the company, the development experience, the users' thumbs ups, amazements, and "this app is life changing" comments, the number of milestone celebration in All You Can Eat restaurants each years, the number of people rising up from…
saint_abroad · 2019-08-23
> Once you accept bloat, it’s very hard to claw it back. If your project has multi-minute compiles, people won’t even notice a 10s regression in compile time. Then these pile up, and it gets harder and harder to motivate the work to reduce bloat, because each second gained in compile time becomes such a small fraction of the total. https://raphlinus.github.io/rust/2019/08/21/rust-bloat.html
If accepting a feature that causes a 3x compile-time regression were easy, then that 29s build is just 5 easy decisions away from a 2-hour build. Now, nobody cares about adding more time to the builds, since nightly, and developers commit hoping it doesn't fail. This is sadly all too familiar.
> Good programmers write good code. Great programmers write no code. Zen programmers delete code. https://www.quora.com/What-are-some-things-that-only-someone-who-has-b…
bananapub · 2026-04-08
raph wrote about that already: https://raphlinus.github.io/rust/gui/2022/07/15/next-dozen-guis.html#a…
signa11 · 2025-11-05
also the (companion) blog post (for a good parallel computer) https://raphlinus.github.io/gpu/2025/03/21/good-parallel-computer.html