Skip to main content
When the declarative node types aren’t enough, ui.web() embeds a real Android WebView directly inside your surface or page, giving you access to the full HTML, CSS, and JavaScript stack. Use it for custom visualizations, rich layouts, or any interaction model that the native node set doesn’t cover.

API signature

Options

html
string
required
The complete HTML content to render inside the WebView. This is a full HTML document string — include <!DOCTYPE html> and a <body> for reliable rendering across Android versions.
height
number
Explicit height in dp. If omitted, the WebView fills the available vertical space in its container.

What’s enabled in the WebView

The following capabilities are enabled by default in every ui.web() WebView:
  • JavaScript execution<script> tags and inline handlers run normally.
  • DOM storagelocalStorage and sessionStorage are available.
  • Network access — fetch, XMLHttpRequest, and WebSocket connect to remote hosts.
  • File access — the WebView can read from the local filesystem.
  • Content access — Android content:// URIs resolve correctly.

Bidirectional communication — Aether.postMessage

Aether injects a global Aether object into every WebView. Call Aether.postMessage(jsonString) from your JavaScript code to invoke a registered extension action:
The message must be a JSON-serialised string. The top-level action field names the registered action to invoke; args is an optional object forwarded to the action handler as its payload.

Full example — WebView with action bridge

index.ts
When the user taps the button, the WebView calls Aether.postMessage, which invokes the "web-clicked" action registered in the extension. The action handler receives { source: "button" } as its payload and surfaces a notification toast.

Injecting dynamic data

Because html is a normal JavaScript string, you can interpolate values from storage, state, or any render-context field at render time:
Aether calls render every time the extension’s state is invalidated, so the WebView content stays in sync with your extension’s persisted storage.
The WebView has full network access. Do not render untrusted HTML content or resolve external URLs without considering the security implications. An attacker who can influence the html value can execute arbitrary JavaScript with access to the Aether.postMessage bridge and all enabled device capabilities.
Use Aether.postMessage for any interaction that needs to trigger extension logic — state updates, notifications, navigation, or service calls. The message must be a JSON string with an action field and an optional args object. There is no return value from postMessage; use storage and aether.invalidate() to push updated data back into the WebView on the next render.