diff --git a/Cargo.toml b/Cargo.toml
index afae137..e8cfff7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,10 @@ members = [
"crates/weft-runtime",
"crates/weft-servo-shell",
]
+exclude = [
+ "examples/org.weft.demo.counter",
+ "examples/org.weft.demo.notes",
+]
resolver = "2"
[workspace.package]
diff --git a/crates/weft-servo-shell/SERVO_PIN.md b/crates/weft-servo-shell/SERVO_PIN.md
index 0b527b3..c5511a2 100644
--- a/crates/weft-servo-shell/SERVO_PIN.md
+++ b/crates/weft-servo-shell/SERVO_PIN.md
@@ -10,12 +10,14 @@
| Crate | `servo` (package name as of 2026-03-11; previously `libservo`) |
| Feature | `servo-embed` (optional; off by default) |
-## Adding the Cargo dependencies
+## Cargo dependencies
-The Servo deps are **not** in `Cargo.toml` by default to avoid pulling the
-Servo monorepo (~1 GB) into every `cargo check` cycle. To activate, add the
-following to `crates/weft-servo-shell/Cargo.toml` and change the `servo-embed`
-feature line to declare `dep:servo`, `dep:winit`, and `dep:softbuffer`:
+The Servo deps are wired in `crates/weft-servo-shell/Cargo.toml` and
+`crates/weft-app-shell/Cargo.toml` under the `servo-embed` optional feature.
+They are off by default to avoid pulling the Servo monorepo (~1 GB) into every
+`cargo check` cycle.
+
+Current `Cargo.toml` block (already committed):
```toml
[features]
@@ -37,7 +39,7 @@ version = "0.4"
optional = true
```
-Then build:
+To build:
```sh
cargo build -p weft-servo-shell --features servo-embed
@@ -75,17 +77,15 @@ DMA-BUF buffer sharing with the compositor transparently.
- **GAP-1**: ~~Wayland input events not forwarded to Servo~~ **Resolved** — keyboard and
mouse events forwarded via `webview.notify_input_event`; key mapping in `keyutils.rs`.
-- **GAP-2**: EGL `WindowRenderingContext` path scaffolded (`WEFT_EGL_RENDERING=1`).
- When EGL is active, Servo presents frames via surfman's `eglSwapBuffers`; Mesa handles
- DMA-BUF buffer sharing with the compositor transparently — no explicit
- `zwp_linux_dmabuf_v1` code is needed in the shell for basic rendering.
- The `zweft_shell_manager_v1` event queue is now dispatched each frame so `configure`,
- `focus_changed`, and `window_closed` events are processed; `window_closed` triggers a
- clean Servo shutdown.
- Remaining gap: the `ZweftShellWindowV1` is created with `surface = null`; the winit
- `wl_surface` is not yet associated with the shell window slot (requires sharing a single
- Wayland connection between winit and the shell client, which is not currently feasible
- without significant refactoring).
+- **GAP-2**: ~~`ZweftShellWindowV1` created with `surface = null`~~ **Resolved** —
+ `ShellClient::connect_with_display(display_ptr, surface_ptr)` uses
+ `Backend::from_foreign_display` to share winit's `wl_display` connection; the winit
+ `wl_surface` pointer is passed directly to `create_window`, associating the compositor
+ shell slot with the actual rendered surface. `ShellClient` is now constructed inside
+ `resumed()` after the winit window exists, not before the event loop. EGL path and
+ per-frame event dispatch are unchanged.
+ Protocol note: `wayland-scanner 0.31` generates `_type` (not `r#type`) for the
+ `navigation_gesture` event arg named `type`.
- **GAP-3**: WebGPU adapter on Mesa may fail CTS — validation task, requires Mesa GPU hardware.
- **GAP-4**: ~~CSS Grid~~ **Grid resolved** (Taffy-backed, fully wired).
~~CSS `backdrop-filter` unimplemented~~ **`backdrop-filter` resolved** (servo/servo issue
diff --git a/examples/keys/weft-sign.key b/examples/keys/weft-sign.key
new file mode 100644
index 0000000..2f8e510
--- /dev/null
+++ b/examples/keys/weft-sign.key
@@ -0,0 +1 @@
+6322e10dadbbe0f0d95fa113278392eac87768826167dd1cfcb3cc1cb7e43312
\ No newline at end of file
diff --git a/examples/keys/weft-sign.pub b/examples/keys/weft-sign.pub
new file mode 100644
index 0000000..46363ed
--- /dev/null
+++ b/examples/keys/weft-sign.pub
@@ -0,0 +1 @@
+470490314923b5f51d96196a6dee67e831f0b758119b8558d83cf415088fe062
\ No newline at end of file
diff --git a/examples/org.weft.demo.counter/.cargo/config.toml b/examples/org.weft.demo.counter/.cargo/config.toml
new file mode 100644
index 0000000..f68f33c
--- /dev/null
+++ b/examples/org.weft.demo.counter/.cargo/config.toml
@@ -0,0 +1,2 @@
+[build]
+target = "wasm32-wasip2"
diff --git a/examples/org.weft.demo.counter/Cargo.lock b/examples/org.weft.demo.counter/Cargo.lock
new file mode 100644
index 0000000..3732df2
--- /dev/null
+++ b/examples/org.weft.demo.counter/Cargo.lock
@@ -0,0 +1,321 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "anyhow"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "bitflags"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
+[[package]]
+name = "indexmap"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
+
+[[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "org-weft-demo-counter"
+version = "0.1.0"
+dependencies = [
+ "serde_json",
+ "wit-bindgen",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "wasm-encoder"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
+dependencies = [
+ "bitflags",
+ "hashbrown",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e915216dde3e818093168df8380a64fba25df468d626c80dd5d6a184c87e7c7"
+dependencies = [
+ "bitflags",
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "863a7ab3c4dfee58db196811caeb0718b88412a0aef3d1c2b02fcbae1e37c688"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d14f3a9bfa3804bb0e9ab7f66da047f210eded6a1297ae3ba5805b384d64797f"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929"
+dependencies = [
+ "anyhow",
+ "hashbrown",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/examples/org.weft.demo.counter/Cargo.toml b/examples/org.weft.demo.counter/Cargo.toml
new file mode 100644
index 0000000..a111dc6
--- /dev/null
+++ b/examples/org.weft.demo.counter/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "org-weft-demo-counter"
+version = "0.1.0"
+edition = "2024"
+
+[[bin]]
+name = "app"
+path = "src/main.rs"
+
+[dependencies]
+wit-bindgen = "0.53"
+serde_json = "1"
+
+[profile.release]
+opt-level = "z"
+strip = true
+lto = true
diff --git a/examples/org.weft.demo.counter/app.wasm b/examples/org.weft.demo.counter/app.wasm
new file mode 100644
index 0000000..4bc6854
Binary files /dev/null and b/examples/org.weft.demo.counter/app.wasm differ
diff --git a/examples/org.weft.demo.counter/signature.sig b/examples/org.weft.demo.counter/signature.sig
new file mode 100644
index 0000000..daeb4c1
--- /dev/null
+++ b/examples/org.weft.demo.counter/signature.sig
@@ -0,0 +1 @@
+4d26abef46af41b1992c0592313ea6aeb39b21eb4a31b978c13ed7c46b444f4d3469819eec1e9d3a00ef40898b77cc3391edfac55fcc50e13817a9eaf126ec0a
\ No newline at end of file
diff --git a/examples/org.weft.demo.counter/src/main.rs b/examples/org.weft.demo.counter/src/main.rs
new file mode 100644
index 0000000..57067be
--- /dev/null
+++ b/examples/org.weft.demo.counter/src/main.rs
@@ -0,0 +1,42 @@
+wit_bindgen::generate!({
+ path: "wit",
+ world: "app",
+ with: {
+ "weft:app/notify@0.1.0": generate,
+ "weft:app/ipc@0.1.0": generate,
+ },
+});
+
+use weft::app::{ipc, notify};
+
+fn main() {
+ notify::ready();
+
+ let mut count: i32 = 0;
+
+ loop {
+ if let Some(raw) = ipc::recv() {
+ let reply = match raw.trim() {
+ "increment" => {
+ count += 1;
+ format!("{{\"count\":{count}}}")
+ }
+ "decrement" => {
+ count -= 1;
+ format!("{{\"count\":{count}}}")
+ }
+ "reset" => {
+ count = 0;
+ format!("{{\"count\":{count}}}")
+ }
+ "get" => {
+ format!("{{\"count\":{count}}}")
+ }
+ _ => continue,
+ };
+ let _ = ipc::send(&reply);
+ } else {
+ std::thread::sleep(std::time::Duration::from_millis(10));
+ }
+ }
+}
diff --git a/examples/org.weft.demo.counter/ui/index.html b/examples/org.weft.demo.counter/ui/index.html
new file mode 100644
index 0000000..50e535d
--- /dev/null
+++ b/examples/org.weft.demo.counter/ui/index.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+Counter
+
+
+
+
+
Counter
+
0
+
+
+
+
+
+
connecting…
+
+
+
+
+
diff --git a/examples/org.weft.demo.counter/wapp.toml b/examples/org.weft.demo.counter/wapp.toml
new file mode 100644
index 0000000..41440e0
--- /dev/null
+++ b/examples/org.weft.demo.counter/wapp.toml
@@ -0,0 +1,12 @@
+[package]
+id = "org.weft.demo.counter"
+name = "Counter"
+version = "0.1.0"
+description = "Stateless counter demonstrating weft:app/ipc"
+author = "WEFT OS"
+
+[runtime]
+module = "app.wasm"
+
+[ui]
+entry = "ui/index.html"
diff --git a/examples/org.weft.demo.counter/wit/deps/weft-app/weft-app.wit b/examples/org.weft.demo.counter/wit/deps/weft-app/weft-app.wit
new file mode 100644
index 0000000..7d7e746
--- /dev/null
+++ b/examples/org.weft.demo.counter/wit/deps/weft-app/weft-app.wit
@@ -0,0 +1,38 @@
+package weft:app@0.1.0;
+
+interface notify {
+ ready: func();
+}
+
+interface ipc {
+ send: func(payload: string) -> result<_, string>;
+ recv: func() -> option;
+}
+
+interface fetch {
+ record response {
+ status: u16,
+ content-type: string,
+ body: list,
+ }
+
+ fetch: func(
+ url: string,
+ method: string,
+ headers: list>,
+ body: option>,
+ ) -> result;
+}
+
+interface notifications {
+ notify: func(
+ title: string,
+ body: string,
+ icon: option,
+ ) -> result<_, string>;
+}
+
+interface clipboard {
+ read: func() -> result;
+ write: func(text: string) -> result<_, string>;
+}
diff --git a/examples/org.weft.demo.counter/wit/world.wit b/examples/org.weft.demo.counter/wit/world.wit
new file mode 100644
index 0000000..37c2d3c
--- /dev/null
+++ b/examples/org.weft.demo.counter/wit/world.wit
@@ -0,0 +1,6 @@
+package org:weft-demo-counter@0.1.0;
+
+world app {
+ import weft:app/notify@0.1.0;
+ import weft:app/ipc@0.1.0;
+}
diff --git a/examples/org.weft.demo.notes/.cargo/config.toml b/examples/org.weft.demo.notes/.cargo/config.toml
new file mode 100644
index 0000000..f68f33c
--- /dev/null
+++ b/examples/org.weft.demo.notes/.cargo/config.toml
@@ -0,0 +1,2 @@
+[build]
+target = "wasm32-wasip2"
diff --git a/examples/org.weft.demo.notes/Cargo.lock b/examples/org.weft.demo.notes/Cargo.lock
new file mode 100644
index 0000000..1300684
--- /dev/null
+++ b/examples/org.weft.demo.notes/Cargo.lock
@@ -0,0 +1,321 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "anyhow"
+version = "1.0.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "bitflags"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
+[[package]]
+name = "indexmap"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
+
+[[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "org-weft-demo-notes"
+version = "0.1.0"
+dependencies = [
+ "serde_json",
+ "wit-bindgen",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "wasm-encoder"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
+dependencies = [
+ "bitflags",
+ "hashbrown",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e915216dde3e818093168df8380a64fba25df468d626c80dd5d6a184c87e7c7"
+dependencies = [
+ "bitflags",
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "863a7ab3c4dfee58db196811caeb0718b88412a0aef3d1c2b02fcbae1e37c688"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d14f3a9bfa3804bb0e9ab7f66da047f210eded6a1297ae3ba5805b384d64797f"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.245.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929"
+dependencies = [
+ "anyhow",
+ "hashbrown",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/examples/org.weft.demo.notes/Cargo.toml b/examples/org.weft.demo.notes/Cargo.toml
new file mode 100644
index 0000000..8f9731a
--- /dev/null
+++ b/examples/org.weft.demo.notes/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "org-weft-demo-notes"
+version = "0.1.0"
+edition = "2024"
+
+[[bin]]
+name = "app"
+path = "src/main.rs"
+
+[dependencies]
+wit-bindgen = "0.53"
+serde_json = "1"
+
+[profile.release]
+opt-level = "z"
+strip = true
+lto = true
diff --git a/examples/org.weft.demo.notes/app.wasm b/examples/org.weft.demo.notes/app.wasm
new file mode 100644
index 0000000..bd523ab
Binary files /dev/null and b/examples/org.weft.demo.notes/app.wasm differ
diff --git a/examples/org.weft.demo.notes/signature.sig b/examples/org.weft.demo.notes/signature.sig
new file mode 100644
index 0000000..feb4212
--- /dev/null
+++ b/examples/org.weft.demo.notes/signature.sig
@@ -0,0 +1 @@
+e781544104eee4538e17f953ea3223903e2b2a46a78705cd1ffa8d6946a62d0385c76eab2cc1c2533eecbeff7600e76a4205abc66915be8851fe2e71316ebc0d
\ No newline at end of file
diff --git a/examples/org.weft.demo.notes/src/main.rs b/examples/org.weft.demo.notes/src/main.rs
new file mode 100644
index 0000000..485544e
--- /dev/null
+++ b/examples/org.weft.demo.notes/src/main.rs
@@ -0,0 +1,59 @@
+wit_bindgen::generate!({
+ path: "wit",
+ world: "app",
+ with: {
+ "weft:app/notify@0.1.0": generate,
+ "weft:app/ipc@0.1.0": generate,
+ },
+});
+
+use weft::app::{ipc, notify};
+
+const NOTES_PATH: &str = "/data/notes.txt";
+
+fn load_notes() -> String {
+ std::fs::read_to_string(NOTES_PATH).unwrap_or_default()
+}
+
+fn save_notes(text: &str) -> Result<(), String> {
+ std::fs::write(NOTES_PATH, text).map_err(|e| e.to_string())
+}
+
+fn json_text(text: &str) -> String {
+ let escaped = text
+ .replace('\\', "\\\\")
+ .replace('"', "\\\"")
+ .replace('\n', "\\n")
+ .replace('\r', "\\r")
+ .replace('\t', "\\t");
+ format!("{{\"text\":\"{escaped}\"}}")
+}
+
+fn json_error(msg: &str) -> String {
+ let escaped = msg.replace('"', "\\\"");
+ format!("{{\"error\":\"{escaped}\"}}")
+}
+
+fn main() {
+ notify::ready();
+
+ loop {
+ if let Some(raw) = ipc::recv() {
+ let raw = raw.trim().to_owned();
+ let reply = if raw == "load" {
+ json_text(&load_notes())
+ } else if let Some(rest) = raw.strip_prefix("save:") {
+ let text = rest.replace("\\n", "\n");
+ match save_notes(&text) {
+ Ok(()) => json_text(&text),
+ Err(e) => json_error(&e),
+ }
+ } else {
+ continue;
+ };
+ let _ = ipc::send(&reply);
+ } else {
+ std::thread::sleep(std::time::Duration::from_millis(10));
+ }
+ }
+}
diff --git a/examples/org.weft.demo.notes/ui/index.html b/examples/org.weft.demo.notes/ui/index.html
new file mode 100644
index 0000000..e0592e5
--- /dev/null
+++ b/examples/org.weft.demo.notes/ui/index.html
@@ -0,0 +1,164 @@
+
+
+
+
+
+Notes
+
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/org.weft.demo.notes/wapp.toml b/examples/org.weft.demo.notes/wapp.toml
new file mode 100644
index 0000000..a052d45
--- /dev/null
+++ b/examples/org.weft.demo.notes/wapp.toml
@@ -0,0 +1,13 @@
+[package]
+id = "org.weft.demo.notes"
+name = "Notes"
+version = "0.1.0"
+description = "Persistent notes demonstrating fs:rw:app-data via weft:app/ipc"
+author = "WEFT OS"
+capabilities = ["fs:rw:app-data"]
+
+[runtime]
+module = "app.wasm"
+
+[ui]
+entry = "ui/index.html"
diff --git a/examples/org.weft.demo.notes/wit/deps/weft-app/weft-app.wit b/examples/org.weft.demo.notes/wit/deps/weft-app/weft-app.wit
new file mode 100644
index 0000000..7d7e746
--- /dev/null
+++ b/examples/org.weft.demo.notes/wit/deps/weft-app/weft-app.wit
@@ -0,0 +1,38 @@
+package weft:app@0.1.0;
+
+interface notify {
+ ready: func();
+}
+
+interface ipc {
+ send: func(payload: string) -> result<_, string>;
+ recv: func() -> option;
+}
+
+interface fetch {
+ record response {
+ status: u16,
+ content-type: string,
+ body: list,
+ }
+
+ fetch: func(
+ url: string,
+ method: string,
+ headers: list>,
+ body: option>,
+ ) -> result;
+}
+
+interface notifications {
+ notify: func(
+ title: string,
+ body: string,
+ icon: option,
+ ) -> result<_, string>;
+}
+
+interface clipboard {
+ read: func() -> result;
+ write: func(text: string) -> result<_, string>;
+}
diff --git a/examples/org.weft.demo.notes/wit/world.wit b/examples/org.weft.demo.notes/wit/world.wit
new file mode 100644
index 0000000..0f10f78
--- /dev/null
+++ b/examples/org.weft.demo.notes/wit/world.wit
@@ -0,0 +1,6 @@
+package org:weft-demo-notes@0.1.0;
+
+world app {
+ import weft:app/notify@0.1.0;
+ import weft:app/ipc@0.1.0;
+}