§Oxide — The Binary-First WebAssembly Browser
https://docs.oxide.foundation
Oxide is a binary-first browser that fetches and executes .wasm
(WebAssembly) modules instead of HTML/JavaScript. Guest applications run
in a secure sandbox with zero access to the host filesystem, environment
variables, or raw network sockets. The browser exposes a rich set of
capability APIs that guest modules import to interact with the host.
The desktop shell is built on GPUI (Zed’s
GPU-accelerated UI framework). Guest draw commands map directly onto GPUI
primitives — filled quads, GPU-shaped text, vector paths, and image
textures — giving your canvas output full hardware acceleration.
§Crate Map
| Crate | Purpose | Audience |
oxide_sdk | Guest SDK — safe Rust wrappers for the "oxide" host imports | App developers |
oxide_browser | Host runtime — Wasmtime engine, sandbox, GPUI shell | Browser contributors |
§Quick Start — Building a Guest App
# Cargo.toml
[package]
name = "my-oxide-app"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
oxide-sdk = "0.6"
§Static app (one-shot render)
ⓘuse oxide_sdk::*;
#[no_mangle]
pub extern "C" fn start_app() {
log("Hello from Oxide!");
canvas_clear(30, 30, 46, 255);
canvas_text(20.0, 40.0, 28.0, 255, 255, 255, 255, "Welcome to Oxide");
}
ⓘuse oxide_sdk::*;
#[no_mangle]
pub extern "C" fn start_app() { log("Ready"); }
#[no_mangle]
pub extern "C" fn on_frame(_dt_ms: u32) {
canvas_clear(30, 30, 46, 255);
let (mx, my) = mouse_position();
canvas_circle(mx, my, 20.0, 255, 100, 100, 255);
if ui_button(1, 20.0, 20.0, 100.0, 30.0, "Click me!") {
log("Clicked!");
}
}
§High-level drawing API
ⓘuse oxide_sdk::draw::*;
#[no_mangle]
pub extern "C" fn start_app() {
let c = Canvas::new();
c.clear(Color::hex(0x1e1e2e));
c.fill_rect(Rect::new(10.0, 10.0, 200.0, 100.0), Color::rgb(80, 120, 200));
c.fill_circle(Point2D::new(300.0, 200.0), 50.0, Color::RED);
c.text("Hello!", Point2D::new(20.0, 30.0), 24.0, Color::WHITE);
}
Build and run:
cargo build --target wasm32-unknown-unknown --release
# Open Oxide browser → navigate to your .wasm file
§Architecture Overview
┌─────────────────────────────────────────────────────┐
│ Oxide Browser │
│ │
│ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ URL Bar │ │ Canvas │ │ Console │ │
│ └────┬─────┘ └──────┬─────┘ └──────┬───────────┘ │
│ │ │ │ │
│ ┌────▼───────────────▼───────────────▼──────────┐ │
│ │ Host Runtime (oxide-browser) │ │
│ │ Wasmtime engine · sandbox policy │ │
│ │ fuel: 500M instructions · memory: 256 MB │ │
│ └────────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────────────────▼──────────────────────────┐ │
│ │ Capability Provider │ │
│ │ "oxide" wasm import module │ │
│ │ canvas · gpu · audio · video · capture │ │
│ │ fetch · streaming · websocket · webrtc · midi │ │
│ │ timers · animation frames · navigation │ │
│ │ console · storage · clipboard · widgets │ │
│ │ input · hyperlinks · crypto · protobuf │ │
│ └────────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────────────────▼──────────────────────────┐ │
│ │ Guest .wasm Module (oxide-sdk) │ │
│ │ exports: start_app(), on_frame(dt_ms) │ │
│ │ imports: oxide::* │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
§Guest SDK API Reference
The oxide_sdk crate provides the full guest-side API. All functions
are available via use oxide_sdk::*;.
§High-Level Drawing API (oxide_sdk::draw)
The oxide_sdk::draw module provides GPUI-inspired ergonomic types
that wrap the low-level canvas functions with less boilerplate:
ⓘuse oxide_sdk::draw::*;
let c = Canvas::new();
c.clear(Color::hex(0x1e1e2e));
c.fill_rect(Rect::new(10.0, 10.0, 200.0, 100.0), Color::rgb(80, 120, 200));
c.fill_circle(Point2D::new(300.0, 200.0), 50.0, Color::RED);
c.text("Hello!", Point2D::new(20.0, 30.0), 24.0, Color::WHITE);
c.line(Point2D::ZERO, Point2D::new(400.0, 300.0), 2.0, Color::YELLOW);
let (w, h) = c.dimensions();
§Low-Level Canvas Drawing
The canvas is the main rendering surface. Coordinates start at (0, 0)
in the top-left corner. Each draw command maps to a GPUI GPU primitive.
ⓘuse oxide_sdk::*;
canvas_clear(30, 30, 46, 255);
canvas_rect(10.0, 10.0, 200.0, 100.0, 80, 120, 200, 255);
canvas_circle(300.0, 200.0, 50.0, 200, 100, 150, 255);
canvas_text(20.0, 30.0, 24.0, 255, 255, 255, 255, "Hello!");
canvas_line(0.0, 0.0, 400.0, 300.0, 255, 200, 0, 255, 2.0);
let (w, h) = canvas_dimensions();
log(&format!("Canvas: {}x{}", w, h));
§Console Logging
§HTTP Networking
All network access is mediated by the host — the guest never opens raw
sockets. Protocol Buffers is the native wire format.
ⓘuse oxide_sdk::*;
let resp = fetch_get("https://api.example.com/data").unwrap();
log(&format!("Status: {}, Body: {}", resp.status, resp.text()));
The oxide_sdk::proto module provides a zero-dependency protobuf
encoder/decoder compatible with the Protocol Buffers wire format.
ⓘuse oxide_sdk::proto::{ProtoEncoder, ProtoDecoder};
let msg = ProtoEncoder::new()
.string(1, "alice")
.uint64(2, 42)
.bool(3, true)
.finish();
let mut decoder = ProtoDecoder::new(&msg);
while let Some(field) = decoder.next() {
match field.number {
1 => log(&format!("name = {}", field.as_str())),
2 => log(&format!("age = {}", field.as_u64())),
_ => {}
}
}
§Storage
§Audio
§Video
Video decoding uses FFmpeg on the host. Frames are rendered as GPUI
textures for GPU-accelerated compositing.
The host shows permission dialogs before granting access to hardware.
§Timers
Timer callbacks fire via the guest-exported on_timer(callback_id) function.
§Animation Frames
Vsync-aligned callbacks for smooth rendering. Callbacks fire via the
guest-exported on_timer(callback_id) function (the same export used by
oxide_sdk::set_timeout), one-shot per request.
§Streaming HTTP
Non-blocking variant of oxide_sdk::fetch that streams the response body
back to the guest in chunks. Returns immediately with a handle; poll
oxide_sdk::fetch_state and oxide_sdk::fetch_recv each frame.
§WebSocket
Long-lived bidirectional connections. Messages are queued on the host and
drained by the guest each frame via oxide_sdk::ws_recv.
§MIDI Devices
Read and write MIDI messages on hardware controllers and synthesisers.
Each input port maintains a bounded queue; long SysEx packets are split.
§GPU
WebGPU-style API for GPU-backed buffers, textures, shaders, and
pipelines. Shader source is WGSL.
§Navigation & History
Widgets are rendered during the on_frame() loop:
§Crypto & Encoding
§Other APIs
§Browser Internals
The oxide_browser crate contains the host-side implementation.
Key modules for contributors:
oxide_browser::engine — Wasmtime engine setup, oxide_browser::engine::SandboxPolicy,
fuel metering, bounded linear memory
oxide_browser::runtime — oxide_browser::runtime::BrowserHost orchestrates module
fetching, compilation, and execution. oxide_browser::runtime::LiveModule keeps interactive
apps alive across frames.
oxide_browser::capabilities — The "oxide" import module: every host function the
guest can call is registered here via register_host_functions(). Also contains shared state
types (oxide_browser::capabilities::HostState, oxide_browser::capabilities::CanvasState,
oxide_browser::capabilities::InputState, etc.).
oxide_browser::navigation — oxide_browser::navigation::NavigationStack implements
browser-style back/forward history with opaque state.
oxide_browser::bookmarks — oxide_browser::bookmarks::BookmarkStore provides
persistent bookmark storage backed by sled.
oxide_browser::url — oxide_browser::url::OxideUrl wraps WHATWG URL parsing with
support for http, https, file, and oxide:// schemes.
oxide_browser::ui — oxide_browser::ui::OxideBrowserView and oxide_browser::ui::run_browser
implement tabbed browsing, toolbar, canvas rendering, console panel, and bookmarks sidebar.
oxide_browser::video, oxide_browser::audio_format, oxide_browser::media_capture —
FFmpeg video pipeline, audio format sniffing, and camera/microphone/screen capture host state.
oxide_browser::gpu — WebGPU-style host state: buffers, textures, shaders, and render/compute pipelines.
oxide_browser::rtc — WebRTC peer connections, data channels, media tracks, and the built-in signalling client.
oxide_browser::websocket — WebSocket host state: connection registry, send/recv queues, and ready-state tracking.
oxide_browser::midi — MIDI input/output port enumeration, bounded receive queues, and packet splitting.
oxide_browser::fetch — Streaming fetch host state: in-flight handles, body chunk queue, and abort tracking.
oxide_browser::download — Background downloader for non-WASM URLs surfaced as files in the host UI.
§Guest Module Contract
Every .wasm module loaded by Oxide must:
- Export
start_app — extern "C" fn() entry point called on load
- Optionally export
on_frame — extern "C" fn(dt_ms: u32) for
interactive apps with a render loop
- Optionally export
on_timer — extern "C" fn(callback_id: u32)
to receive timer callbacks
- Import from
"oxide" — all host APIs live under this namespace
- Compile as
cdylib — crate-type = ["cdylib"] in Cargo.toml
- Target
wasm32-unknown-unknown — no WASI, pure capability-based
§Security Model
| Constraint | Value | Purpose |
| Filesystem access | None | Guest cannot read/write host files |
| Environment variables | None | Guest cannot inspect host env |
| Raw network sockets | None | All networking is mediated via fetch |
| Memory limit | 256 MB (4096 pages) | Prevents memory exhaustion |
| Fuel limit | 500M instructions | Prevents infinite loops / DoS |
| No WASI | — | Zero implicit system access |