Compared
Where Spark sits among the alternatives, including what it gives up.
Every one of them
answers the same question.
How do you draw a window. Electron answers with a browser, Flutter with its own renderer, NodeGui with a bundled runtime.
Spark answers that one with the widget set the machine already has. And a second one that nobody else in a survey of some 180 alternatives asks: can you address what is in it. Every control has a name; a person hears it from a screen reader, a script writes to it, a pipe asks for it, an agent presses it.
Which is checkable, because it is one tree. The first run of
spark cross found twenty-five of twenty-six Windows controls
unreachable without a mouse.
Four camps
| Camp | Examples | What it costs |
|---|---|---|
| WebView | Electron, Tauri, wails, Neutralino, Photino | The UI is HTML rendered by a browser engine. Behaviour follows whichever WebKit the machine has. |
| Own renderer | Flutter, GPUI, Sciter, Kivy | The same everywhere, and nothing in it is native. |
| Widgets via a runtime | NodeGui, Proton Native, Toga, PyQt, Fyne | Real widgets, but Node/Python/Qt/GTK ship with the app. |
| System script host | WelsonJS, HTA | Nothing bundled, and Windows only, with MSHTML doing the rendering. |
Spark is in none of them: real OS widgets, the system's own JavaScript engine, all three desktops, and nothing bundled. In a survey of some 180 alternatives, no project hit all four.
What Spark gives up
- The web platform. No CSS, no arbitrary HTML, nothing off npm. There are components and reactive bindings, but the vocabulary they are built from is fixed and small.
- Windows' engine is old. Chakra is ES5.1. The bundling step makes npm code usable, but that ceiling is real.
- Accessibility goes as far as names and events. Linux speaks AT-SPI
directly over D-Bus, no toolkit involved, and all three publish a name and
announce focus and changes. What is not exposed yet is a slider's value and a
field's contents through the
ValueandTextinterfaces — and no real screen reader has been run against any of the three. - Adding a widget Spark does not map yet is C, in three hosts.
Against the two
you would otherwise pick
Spark's three numbers were taken on this machine:
spark test size for the packed app, the launch of a real window
with its scripts run for the start, and vmmap's physical
footprint for the memory. Tauri's and Electron's are the published figures for
a hello-world app, different machine, different app, same order of magnitude.
Bars are drawn to scale, which is why two of them are almost invisible.
The reason is not cleverness. Electron carries Chromium and Node; Tauri carries a Rust binary and borrows the system's webview; Spark carries neither a renderer nor an engine, because the widgets and the JavaScript are already on the machine.
What it is unusually good at
- Size and idle cost. One file of a few hundred kilobytes, no Chromium in memory, no render loop when nothing moves.
- Measured sameness across three native toolkits. Everyone else with real widgets accepts that each platform looks different; here it is checked on every change, in pixels.
- Accessibility from the same tree. On macOS and Windows the controls are real, so the system does it. On Linux there is no toolkit to inherit from, so Spark answers AT-SPI over D-Bus itself — the accessibility tree and the layout tree are the same tree, which is why the adapter is six hundred lines and not a second widget set.
- Nothing to keep patched. No bundled engine means no bundled engine's security updates.
- Addressable from outside. Every control has a name a program can ask for and act on, and the document can say which programs may. This is the one on the list nobody else has.
Why nobody else has that one
Tools like Desktop CLI and Touchpoint make existing desktop apps legible to a program by normalising Windows UI Automation, macOS Accessibility and Linux AT-SPI into one graph. That is the right idea and it is harder than it sounds: they get whatever each app's toolkit happened to expose, which is lossy, differs per toolkit, and can change under them at any release.
Spark is not doing the same thing better. It is a layer lower. The tree a program reads is the tree the layout works on, not a reconstruction of it, so nothing is lost in translation and nothing can drift.