This document is the checklist for implementing a new DesktopWebView host.
The Elixir side is shared; only code under native/<platform>/ changes.
Reference implementation: native/macos/ (Swift + WKWebView).
Do not copy macOS UI code into other platforms — share only the protocol.
- protocol.md — wire format, methods, behavioral semantics
- packaging.md — CLI, ini, layouts, release artifacts
- status/<platform>.md — feature matrix for your target
- AGENTS.md — repo rules (E2E-only testing,
--edw-*, etc.)
| Rule | Detail |
|---|---|
| Roles | Native listens; Elixir connects |
| Framing | 4-byte big-endian length + UTF-8 JSON-RPC 2.0 |
| Discovery | Print exactly one line: listening <port> (stdout) |
| Flags | Parse/strip --edw-*; forward the rest to BEAM |
| Env for BEAM | Set EDW_PORT, EDW_HOST when spawning |
| Lifetime | Default reconnect; support coupled |
| Tests | No native unit-test suite as source of truth — pass Elixir E2E |
| Status | Mark docs/status/<platform>.md rows done only when E2E covers them |
- Process shell — argv (
--edw-*), ini discovery, TCP listen,listening <port>,--edw-no-beam - JSON-RPC loop — length-prefixed frames; reject non-
initializeuntil initialized initialize— returnprotocol_version: 1,platform,capabilities- One window + webview —
window.open,webview.load_url/reload/current_url - Close veto — native close →
event.window.close_requested; do not destroy until Elixir says so - Multi-window — resource ids on one TCP connection
- Menus / tray / icons / notifications
- Permissions + mic/camera (hybrid policy)
- OS events — reopen / open URL / open file where the OS supports them
- Packaged BEAM spawn + CI artifact on tag draft releases
- Test RPC behind
--edw-test-rpc; run shared E2E
- Language: C++ or C# (team choice); UI via Win32/WinUI + WebView2
- SDK: Microsoft Edge WebView2 Evergreen Runtime (document bootstrapper needs)
- Build: MSVC; produce
DesktopWebView.exe(x64 required; arm64 optional later) - Artifact name (release):
DesktopWebView-windows-x64.exe(+.sha256)
- Language: C/C++ (or Rust if isolated to this directory)
- UI: GTK 4 + WebKitGTK (WebKitGTK 2.40+ recommended; document exact distro packages in the platform README)
- Build: produce ELF
DesktopWebView(x86_64 required; aarch64 optional later) - Artifact name (release):
DesktopWebView-linux-x86_64(+.sha256) - Tray: prefer StatusNotifierItem / AppIndicator where available; document fallback
menu.set_apple is n/a on Windows and Linux — implement as a successful no-op (true) so Elixir can call it unconditionally.
Until download plumbing lands, local/CI sets:
export DESKTOP_WEBVIEW_BINARY=/path/to/DesktopWebView # or .exeTarget layout after release automation:
| OS | Path / fetch |
|---|---|
| macOS | priv/native/macos/DesktopWebView (vendored) |
| Windows | GitHub Release asset DesktopWebView-windows-x64.exe → cache |
| Linux | GitHub Release asset DesktopWebView-linux-x86_64 → cache |
Shared suite: test/e2e/e2e_test.exs (tag :e2e).
Host must be started with --edw-no-beam --edw-test-rpc.
Before flipping a status row to done, the corresponding E2E (or an added E2E) must pass on that OS. Minimum gate for calling a port “usable”:
| Area | Covered today by |
|---|---|
| RPC + test channel | test.ping, test.echo |
| Window + navigation | window open load reload and list |
| Multi-window | multi-window |
| Menu / tray / icon / notification | menu create and notification |
| Permissions + JS eval | permission policy and simulate |
| Locale / OS string | system locale and os_description |
Platform-specific asserts (e.g. caps["platform"] == "macos") must be generalized when the second host lands — use :os.type() / host initialize.platform.
Add OS matrix jobs in .github/workflows/ci.yml when the binary builds; do not add stub jobs that always fail.
Update docs/status/<platform>.md as you go:
todo— not startedpartial— implemented but no E2E (or known gaps)done— E2E green for that feature on this OSn/a— not applicable (e.g. Apple menu on Windows)
- Keep all UI in
native/<platform>/ - Extend Elixir only for binary download / OS detection if needed
- Update this doc if you discover a cross-platform semantic that was missing
- Link CI artifact names in packaging.md when adding release jobs