Spark reads HTML-ish markup and builds real operating-system
widgets — a real NSButton, a real Win32 button, a real X11 one.
The JavaScript is the engine your system already ships. No browser, no runtime
beside the app. A whole app is one file of a few hundred kilobytes.
<button id="greet">Greet</button>
Not a picture of a button. The real control, with its own focus ring, its own keyboard behaviour, and its own line to VoiceOver and Narrator.



One markup file, three native toolkits, and a layout computed once in shared
C so none of them can disagree about where anything is.
spark cross runs it on all three, checks that every widget landed
where the layout put it, and leaves those screenshots behind. That is how the
pixels are kept the same rather than hoped to be.
AppKit, Win32 and X11 controls — not a canvas pretending to be one.
JavaScriptCore on macOS and Linux, Chakra on Windows. Both already on the machine.
spark pack glues the app onto
the binary. A few hundred KB, not 180 MB.
A real button is exposed to VoiceOver and Narrator. No webview can buy that.
No render loop. The clock runs only while something is actually moving.
Every release runs the same document through macOS, a Linux container and Wine.
| Structure | is layout: <row>,
<col>, <grid>, <stack>,
<scroll> |
|---|---|
| Attributes | are cosmetics: gap, pad,
bg, radius — no CSS, no cascade, no selectors |
| Layout | is computed once, in shared C, because three hosts is three chances to decide the same thing differently |
| JavaScript | is the system's own, and the DOM it sees is a small honest subset |
Debian 11–13, Ubuntu 20.04–24.04, Fedora 41, CentOS 7, Alpine, Windows 10 and 11 including 32-bit, macOS 11 and later — each one started and asked to check its own layout and run the document's scripts. The full table.
git clone https://github.com/eddime/spark-native && cd spark-native
./spark new myapp
./spark dev myapp/index.html
The window opens and every save reloads it — the system says when the file changed, so nothing is polling. Then the rest of the way to a signed app.