Build desktop apps that can’t leak resources. By design, not by discipline.
Gossamer wraps your web frontend in a native window — like Tauri or Electron — but the compiler proves your app handles every resource correctly. Leaked handles, dangling references, and permission bypasses become compile errors instead of production incidents.
Every desktop framework asks you to manage resources carefully. Gossamer makes it impossible to get wrong:
-
Webview handles can’t leak. The type system requires every handle to be properly closed. Forget to close one? The code won’t compile.
-
IPC messages can’t mismatch. Frontend and backend agree on message shapes at compile time, not at runtime when your user hits the bug.
-
Permissions can’t be bypassed. Access control is enforced by the compiler, not by a JSON config file that might have a typo.
-
No garbage collector. Ever. Region-based memory with linear types means deterministic, zero-overhead cleanup. No pauses, no surprises.
| Electron | Tauri | Wails | Gossamer | |
|---|---|---|---|---|
Handle leaks possible? |
Yes |
Yes |
Yes |
No (compile error) |
IPC type-safe? |
No |
Partial |
No |
Yes (compile-time) |
Permission enforcement |
Opt-in |
Runtime config |
None |
Compiler-enforced |
Garbage collector |
V8 + Node GC |
None* |
Go GC |
None, ever |
Smallest binary |
~150MB |
~3MB |
~5MB |
~1MB |
* Tauri uses reference counting internally (Arc<Mutex<…>>).
fn main(): I64 =
let! window = __ffi("gossamer_create", "My App", 800, 600, 1, 1, 0) in
let! _ = __ffi("gossamer_load_html", window, "<h1>Hello!</h1>") in
__ffi("gossamer_run", window)The let! means this handle is linear — it must be used exactly once. Remove the last line and the compiler rejects your program. Try to use window after gossamer_run and the compiler rejects your program. No runtime checks needed.
Your web frontend runs inside the OS webview (WebKitGTK on Linux, WKWebView on macOS, WebView2 on Windows). The backend is written in Ephapax, a language with two binding modes:
-
let x = …— use at most once, implicit cleanup is fine -
let! x = …— use exactly once, compiler enforces it
Resources that matter (windows, connections, file handles) use let!. Everything else uses let. You declare your intent, the compiler enforces it.
Memory is managed through regions — scoped arenas that free everything at once when they exit. Linear types guarantee nothing escapes the region. Result: no GC, no reference counting, no tracing, no overhead.
The native layer is pure Zig calling the OS webview directly. At runtime there’s no VM, no interpreter, no garbage collector. Just your app and the OS.
# Dependencies (Fedora)
sudo dnf install gtk3-devel webkit2gtk4.1-devel zig
# Build the native library
cd src/interface/ffi && zig build
# Build the compiler
git clone https://github.com/hyperpolymath/ephapax
cd ephapax && cargo build -p ephapax-cli
# Run the hello example
cd gossamer && bash examples/hello/run.sh-
v0.1 (released): Linux desktop (WebKitGTK). Working, tested, shipping.
-
v0.2 (in progress): macOS and Windows support.
-
v0.3 (planned): Mobile (iOS and Android).
Gossamer is backed by formal research. The type system and its guarantees are machine-checked in Idris2 and documented in an academic paper:
Gossamer: A Linearly-Typed Webview Shell with Provable Resource Safety — paper source