Why Idealyst over Flutter?Flutter solves a very similar problem: one codebase, every platform, reactive component model. It does that well. The architectural choice it made early — own the renderer everywhere — is exactly the choice Idealyst makes the opposite way.
Same goal, different bottom layerFlutter is mobile-first and ships its own renderer onto every platform — every Material button, every scroll, every text run is painted by Skia (now Impeller on iOS) rather than the OS's own widget. That gives Flutter pixel-identical output across devices but it also means every platform is the same trade-off: Flutter's text is not the OS's text, Flutter's scroll physics are Flutter's scroll physics.Idealyst's per-backend architecture lets each target use whatever fits it best. iOS gets UIKit. macOS gets AppKit. Android gets Android Views. Web gets the DOM. The wgpu backend is there if you want the fully-rendered path, but it isn't the default for platforms that already have a perfectly good toolkit.
The web storyFlutter's web target had genuine growing pains — first an HTML renderer, then CanvasKit, now a canvas-based output that paints the whole app onto a single `<canvas>`. The trade-off is real: text selection, accessibility, browser scroll, view-source, and SEO all behave differently than a normal web page because the page isn't really a normal web page anymore.Idealyst's web backend emits actual DOM nodes. `Text` becomes a `<span>` or `<p>`, `View` becomes a `<div>`, scroll containers use native scrolling. The same author tree that drives UIKit on iOS produces a web page that selects, scrolls, indexes, and prints the way the web is supposed to. The framework also ships an SSR backend for first-paint HTML and progressive enhancement — see the cross-platform page.
Architectural escape hatchFlutter's renderer is part of the framework. If a target needs something the renderer doesn't do, that target has to wait for the renderer to grow that capability. Idealyst's Backend trait is the only seam, and it's a fixed contract — primitives plus styling plus layout plus refs. New target = new implementation of the trait, rest of the framework comes along.