Every keystroke is restyled in under 8ms: no debouncing, no delayed rendering. 20 rapid keystrokes are processed in 150ms with full restyling after each one.
Tag and boolean searches complete in under 20ms. Visible-range rendering is 25x faster than full-document styling. 120Hz screen refresh supported.
App file size was 722 KB for 1.0, and it's looking like 1.1 will be ~950 KB.
If I can do it on iOS then it's must be 10x easier on macOS.
Browser rendering engines are pretty mature at this point, with significant GPU acceleration, and over a decade stress-testing by bloated web apps.
Meanwhile SwiftUI doesn't feel particularly fast. Apple's latest and greatest rewrite of System Preferences has dumbed down the UI to mostly rows of checkboxes, and yet switching between sections can lag worse than loading web pages from us-east-1.
[1] https://notes.alinpanaitiu.com/SwiftUI%20is%20convenient,%20...
The article you cited is from 2022 and so is irrelevant, since SwiftUI's performance profile completely changed as of xOS 26.
Claims like "It's hard to build a performant SwiftUI app" get into skill-issue territory, but more importantly, the reality is there are only "SwiftUI-first apps". All non-trivial SwiftUI-first apps will also use UIKit/AppKit as needed, typically for capabilties that aren't yet available via SwiftUI.
Their point is more that SwiftUI has generally poor performance. Lots of native Windows frameworks have poor performance as well.
Native UI development is a minefield. If you want to build an app today that will still run in 20 years without a complete rewrite in the UI layer you should probably use wxWidgets if you are committed to native - even if only targeting one OS. But that model is really only appropriate for building traditional desktop apps. I don’t think the market would accept a Slack or Notion built that way today.
Even so, there is a stark difference, even more so on low-powered devices, between native apps and even the lightest of browser apps. I'm traditionally a web developer, but started developing native cross-platform applications the last 6-12 months, and the performance gap is pretty big even for simple stuff, strangely enough.
They suck on older hardware. Old Chromebooks are a dime a dozen and are decently spec'd light use or purpose-use machines. Browsers run like crap on them.
If you dig up an 18 year old Core 2 Duo box, upgrade its storage to a cheap SSD, and install Linux on it, it’s shocking how snappy and usable it is for most tasks… up until you open a web browser or Electron app. Then it all falls apart.
Had it not been for resource creep driven overwhelmingly by heavy web apps and Electron/CEF, there’d be little reason for most people to use anything more powerful than a Sandy Bridge machine and we could have laptops and smartphones with week-long battery life thanks to efficiency gains not needing to be consumed by performance increases.
Electron ultimiately sits on native APIs, and has its own performance costs on top of them.
That’s because SwiftUI isn’t particularly good, not because web rendering is as good as native. AppKit still runs circles around both, in performance and resource consumption.
Then the V8 team at Google just asked "well, what if we just made Javascript crazy fast instead?", and here we are. There's still room for native code in environments that don't map nicely to scalar scripting languages, but not a lot of room. Basically everyone is best served by ignoring that the problem ever existed.
It took the rendering side a little longer, but we're here nonetheless. There's still room for specialty apps with real need to exploit the hardware in ways not abstracted by the DOM (not 100% of it is games, but it's close to that). But for general "I need a GUI" problems? Yeah, just use Electron.
Not by a long shot.
How did Microsoft just make Typescript 10x faster? Oh right, by reimplementing it in Go.
https://devblogs.microsoft.com/typescript/typescript-native-...
See also:
https://blog.metaobject.com/2015/10/jitterdammerung.html
Please don't use Electron.
Sorry, sounds like bullsh_t. One can leverage mature markdown renderers in SwiftUI. See https://github.com/gonzalezreal/swift-markdown-ui and its next gen replacement https://github.com/gonzalezreal/textual .
Used these myself and had no issues. And I am a moron who doesn't like Swift or SwiftUI - preferred Objective-C, but still managed to do this, without any LLM help.
- Static completed Markdown scrolling fails the new focused probe. Result: p95 18.86 ms vs 16.7 ms budget, max 232.49 ms.
- Long live Markdown/code update path also fails. Result: p95 59.33 ms vs 16.7 ms, max 75.94 ms. This is a separate but related stress case around large rich text surfaces during updates.
- Long-history scaling technically passes, but the numbers are not smooth-frame healthy: - 120 turns: total p95 21.35 ms - 500 turns: total p95 23.11 ms - 1000 turns: total p95 36.77 ms
Technically, it is not bad. However, it is a bit slower than my own solution & has similar performance gaps, mostly related to SwiftUI rather than the Textual implementation.
Now, if you're rendering everything with WebKit, that's ridiculous, in the same way rendering everything with PDFKit would be ridiculous. But for a Markdown view, WebKit seems like a logical choice. There's no need to subsequently flip the table and replace everything with a Chromium web app.
Also, OS X rendered its UI with DisplayPDF/Quartz for the longest time.
WebKit is cheating I guess? Because it exists on other platforms?
Might as well use Java
It doesn't? Needs an explanation.
I don't understand how you go from "rendering text is completely appropriate" but then "rendering everything is ridiculous".
Because rendering rich text correctly and consistently is one of the hardest problems in software. Bidirectional text, a million glyph shaping complexities, mixed content such as inline images and different text sizes, reflow that should take milliseconds, natural-feeling selection, etc etc.
No implementation comes even close to browser rendering engines in covering all of these.
But WebKit is the native UI for HTML, and Markdown is intended to be transpiled to HTML.
It'd be very silly to render a shader pipeline in WebKit. You could, but with Metal sitting right there, it would be silly.
And yes, I agree: on macOS, WebKit is a native OS framework. In that sense, it is "native". But I think it also supports the broader point I was making: if you want to work with rich text, Markdown, selection, typography, and long-form formatted content properly, web technologies quickly become the only viable option. I am not saying that using WebKit for a Markdown view is wrong. Quite the opposite, it is probably the most reasonable option available. The problem is that the "native" solution here is still effectively a web-rendering solution. There is a cost. Each `WKWebView` brings a WebKit engine with its own performance & memory overhead. So you cannot just sprinkle `WKWebView` everywhere & pretend it is free native macOS component as any other. My frustration is mostly that this is the answer. For this kind of UI, SwiftUI / AppKit / TextKit still do not give you a clean, modern, composable path that feels better than "just use WebKit".
But, like, of course they are. This is what HTML was built for. The other major standard would probably be RTF, but it's a bit less structured, and so less close to Markdown. HTML is the better pick.
If you subsequently want to style that HTML, so that every second-level heading uses a specific font, and every third-level heading uses some other font, and so on, CSS is the best way to do that.
So, yes, we're saying the same thing, but to me it's a bit like saying "If you want to find the answer to 2 + 2, addition is the only viable option." Well, yes!
I think the reason this feels kind of wrong is because that same HTML and CSS renderer you're using for Markdown also comes with an entire 3D graphics pipeline and audio synthesizer. Obviously, we should be able to answer 2 + 2 without opening Mathematica.
I guess the important technical question is whether simply creating a WKWebView also loads in all that other stuff. I would hope and expect the OS is smarter than that, and you can call WebKit for simple HTML without everything else coming along.
Well yeah. If people don't invest sufficient effort in a thing why would there be an expectation for that thing to become mature? People are locked into web tech because that's where the greater majority of the effort has been going. Quite literally people look at native, say it isn't developed enough, and go develop for the web even more. Cycle repeats. Hardly anyone wants to put in the effort to improve native when things already "just work" for the browser.
I think SwiftUI etc al don't work on Linux and Windoes and Android, right? While HTML works?
I’ll reach out to anyone who fills the email form or emails founders@totemkb.com.
And yes, text was definitely a pain, although most of my troubles came from subpixel antialiasing. I might write a post about it soon, I am still not entirely sure whether or not I am just ending up writing a browser in Rust. I did consider Swift at the beginning, but I’m not so much of a purist that I must stick with Swift for MacOS, and I felt fully vindicated as soon as I updated to Tahoe with the frosted glass. For Rust the text library situation can be both better and worse, depending on what you’re looking for.
For now Totem supports Windows, MacOS, Ubuntu, and iOS (Testflight).
Rendering text into things like chat bubbles or even just generic output panes as it comes in is a massive pain. Every new word requires redoing layout, detecting LTR versus RTL flows and overrides, figuring out word breaks and line breaks, possibly combined with resizing the containing UI element (which involves measuring the render space, which is often implemented by rendering to a dummy canvas and finding out the limits).
Document editors have it relatively easy because humans type at a relatively low speed and pasting is a single operation (although pasting large amounts of text does hit the render performance of the UI). They're also often provide relatively limited features on phones.
If you want to render something like ChatGPT with similar features in native UI, youre going to need to find a fully-fledged document component or build one yourself. And, as it turns out, we have document components that work quite well: web engines.
If you embed a webview rendering just HTML and CSS, you get better performance, features, and accessibility than any home-grown renderer will provide. And with every major OS coming with a browser built in, it won't even bloat your app.
What? No. This is like building a Slack clone without the ability to copy a stream of messages. It is entirely reasonable to want to do this.
https://developer.apple.com/documentation/swiftui/link
I'm not sure how much easier they can make it at this point.
Even in an era of PWAs and highly reactive UIs, the web is still fundamentally a document presentation mechanism. No generic GUI toolkit fits that description (even if they can be coerced into being one).
That said, I also had quite a lot of success on iOS 4 using HTML as the layout engine for the main screen of the app, though the place ran out of money before that went anywhere.
HTML can be really good, the blockers back then were it not being exactly the same as the Apple UI guidelines unless you put in a huge amount of extra work that nobody wanted to spend. I'm not sure when Apple's own guidelines stopped mattering exactly (iOS 7's invisible buttons necessarily had to be ignored, but there was already a decent level of custom UI before them and it was already essentially irrelevant even before Apple became extra-inconsistent with Liquid Glass), but I think we're now at the point where you only follow those guidelines if you (a) don't have your own UI team, and/or (b) want to try to aim for a shout-out from Apple.
I'm using what I learned to create a native LLM client with a streaming Markdown parser[2].
Skill issue, I guess. I even tried your SSTextView (which is a very nice piece of software, by the way), though it does fit here, but I tried to understand how wrong my TextKit2 implementation is. In my tests, the SSTextView performed a bit worse with p95 on the static markdown scroll test (70.20 ms vs 16.7 ms for per frame rendering). But it is clear from the traces that SSTextView just does too many things I do not need. At least, I had my confirmation that I am not completely wrong about TextKit.
You can still use native controls for the rest of the UI and have 0 Javascript running. I'm not sure I understand what the problem with NSTextView was though. It's pretty performant as far as I can tell?
Not exactly sure what “streaming” text is, but serial terminal software has been handling incremental text rendering and updating for decades, without performance struggles.
By "streaming" text, I mean a formatted text stream that has to be parsed, formatted, and appended on the fly - basically how every model/AI chat works now. And this is where `NSTextView` becomes tricky. It forces an interesting architectural choice: either go deeper into AppKit with `NSCollectionView`, custom cells, manual layout, etc., or fight the whole SwiftUI model by embedding something like `NSTextView` inside `LazyVStack` / SwiftUI views & then dealing with all the integration problems.
So I am not saying Cocoa / AppKit was always bad, or that `NSTextView` is useless. I am saying that for modern chat-style UI with incrementally rendered formatted text, it does not compose well with the rest of the modern Apple stack.
There’s really nothing else out there that competes with a similar performance and productivity.
This old article by the Missive team (the email client) convinced me.
https://medium.com/missive-app/our-dirty-little-secret-cross...
Skill issue, I guess. /s
Wayland is another product of this hardships, going wayland native seems only feasible when all stars align around it. But then you are stuck in that place.
That being said, without deeper knowledge about SwiftUI, I find it a bit odd to expect so much from a novel concept. Native desktop dev is already kind of niche, considering the dominance of web dev. Chrome (and it's artifacts) is probably the best funded software in the world and google's incentive to improve it is above all. It's not a miracle that it just works. It's effort and tons of cash.
This is a common misconception among programmers, and is actually the opposite of the truth. Drawing arbitrary geometric shapes is easy, rendering text correctly is insanely difficult because ... humans.
Basic text styles are ok, but things like authored pagination, page header/footer, mirrored margins, margin notes, footnotes and references are basically unsupported or need to be hacked together.
Agreed. In Chromium all the content from HTML is rendered inside a single object from the point of view of the host UI; much like a game engine’s UI rendering. Chromium draws everything itself. Host events like mouse and keyboard events are sent to that top level object (although there are some shenanigans involved to make it look more native to accessibility tools).
Or well... since we now have Claude I might have a jab at this someday in my free time.
Both are actually lightweight HTML rendering libraries, so you need to compile markdown to HTML to use them. But there are many libraries for that.
Of course blitz doesn't expose a FFI either and also if you need anything interactive you have to use the dioxius framework or implement you own APIs for that as well as take care of animation yourself.
litehtml appears to have no built-in text input support so far as I can see.
You can do a couple days to a week of reading to understand the fundamentals once and then you will actually know what you are doing.
It is not proper to choose things on “battle tested” or other meaningless words
Fancy text rendering/editing is hard to implement when you leave the luxury of webviews.
But then, what’s the point in using an inherently laggy technique to save memory?
This is my pet project, a desktop app for working with xAI models & capabilities, so by "performance" I mostly mean "pleasant to use" (as it goes, simple & opinionated). Technically speaking, something like: stable FPS, no visible lags, and the ability to scroll smoothly while the model is streaming.
Regarding the parent comment: yes, memory is important, and I absolutely get the point. There should be a red line, for sure. But I will not sacrifice UX, productivity, and simple pleasure from using software just to save a few hundred megabytes of RAM (or even a few gigabytes) especially for an app I spend hours with behind the screen.
Memory consumption can & should be optimised with proper engineering for sure. As lags & inadequate performance in basic SDK-level primitives are much harder (impossible?) to fix from the outside.
What's the point of having 64-128GB of RAM if we're using apps that eat 10GB to do the same things we were doing 20 years ago using a few MB?
a fast performant incomplete solution will lose to a slow correct complete one
I think this may be a misundertstanding of what SwiftUI is. SwiftUI makes it convenient to create apps that look and behave in a way that align with Apple's HIG using controls like `List`, `Form`, etc., but nothing makes you use any of those. For example, it's straightfoward to build a game engine on SwiftUI. https://blog.jacobstechtavern.com/p/swiftui-game-engine
And yes WPF is a framework native to the Windows platform ecosystem.
Where is the profile? Where is the bottleneck?
Just complaining with nothing to contribute.
that's it, for everything else native UIs are complete garbage compared to HTML/CSS/reactive frameworks.
I remember spending 4 hours to make a scrollable element that wasn't jumpy or buggy. There were several stackoverflow answers full of gotchas explaining all you had to do. I finished and published the app but never again. Native stuff has terrible developer experience.
There are even parts of both Windows and MacOS rendered through HTML. If I remember correctly, at least in Windows 10, File Explorer was rendered through Internet Explorer.
Web rendering doesn't need to be only through Electron/Node. There are other libraries much more performant and lean (Dioxus, etc).
Not in the world of macOS and iOS at least. Here native apps still rule, as there's literally no performant alternative (the OP's complaints about Markdown are misplaced - there's been no interest in MD and SwiftUI and that's why there's no good option. But in ObjC/Swift there is).
In fact, most of the apps I am using on a day to day is native. The Electron apps I use are okay (e.g. Slack) but they absolutely fail the native Turing test.
The browser is faster because they went native, in particular, GPU.
Every issue described is text rendering related. Everyone.
And I would bet most of the SwiftUI issues could be solved with a text render cache.
Something like Casey Murati's refterm toy that showed what that can do with no other optimizations, or the work for GPU accelerated terminal emulators like alacritty or ghostty.