WebView & Browser Embedding
Glyx uses a purpose-built GPU renderer with no browser engine — fast
startup, small binaries, consistent cross-platform rendering. That also
means libraries that depend on a real browser (maps, PDF viewers, rich
text editors built on contenteditable) don't work out of the box.
<WebView> embeds the native OS browser control (WebView2 on Windows,
WKWebView on macOS, WebKitGTK on Linux, via wry (opens in a new tab))
as a real child window, position-tracked to the component's layout rect —
the same escape-hatch role Electron's <webview> tag or a Tauri
system-webview child window plays.
Requires webview: true in glyx.config.json capabilities (or it's
included automatically if capabilities are unspecified). The webview
runs as a separate glyx-cap-webview native module, loaded dynamically —
not statically linked into glyx-core — matching how audio/camera/AI
capabilities are structured.
What needs WebView
| Use case | Why it needs a browser |
|---|---|
| Interactive maps (Leaflet, Mapbox GL, Google Maps) | Depend on WebGL or HTML canvas inside a browser compositor |
| PDF viewer | pdf.js renders into a browser canvas |
| Portal & intranet pages | HTML pages you or your company own, embedded as-is |
| Third-party web dashboards | Grafana, Metabase, or any iframe-based embed |
| Rich text editors (Slate, TipTap, Quill) | Built on contenteditable and DOM selection APIs |
<video> with DRM | Requires browser CDM integration |
If the content is your own web app, consider whether it can be rewritten as a native Glyx screen instead — better performance, tighter OS integration. WebView is the right call for content you don't control, or where porting would be impractical.
For simple map-like UIs, Canvas 2D can cover it without a browser at all —
static tile grids (ctx.drawImage over fetched PNG tiles), route/heatmap
overlays via the path API, or pin/label markers with ctx.fillText. Good
for dashboards showing fixed-background data; not a substitute for
interactive street maps with full pan/zoom/labels.
Basic usage
import { WebView } from '@glyx-dev/react'
<WebView src="https://example.com" style={{ width: 800, height: 600 }} />Raw HTML, no network required:
<WebView html="<h1>hi</h1>" style={{ flex: 1 }} />Local files bundled with your app, served over glyx-asset://:
<WebView src="glyx-asset://index.html" assetsRoot="C:/app/assets" style={{ flex: 1 }} />Props
| Prop | Type | Description |
|---|---|---|
src | string | URL or glyx-asset:// path to load. Ignored if html is set. |
html | string | Raw HTML to load directly — no network, no navigation. |
sandbox | boolean (default true) | Devtools off, strict navigation. Set false to relax. |
allowedOrigins | string[] | Navigation allowlist. Omitted/empty = only the initial URL's own origin is navigable — clicking an external link inside the page won't leave that origin. |
assetsRoot | string | Enables glyx-asset://<path> to serve files from this directory. |
onMessage | (msg: string) => void | Called when the page sends a message via window.ipc.postMessage(str). |
style | layout style | Same layout system as every other Glyx component — the webview is position-tracked to this rect every frame. |
Two-way messaging
Frames/content never cross the JS bridge — only postMessage strings do.
Page → JS: inside the embedded page's own script, call
window.ipc.postMessage(str) (injected automatically by wry). It arrives
as the onMessage prop's argument.
JS → page: use a ref to call postMessage on the component; the page
receives it via the standard window.addEventListener('message', ...).
import { useRef } from 'react'
import { WebView } from '@glyx-dev/react'
const PAGE_HTML = `<!doctype html><html><body>
<button onclick="window.ipc.postMessage('hello from page')">Send</button>
<script>
window.addEventListener('message', e => console.log('from JS:', e.data))
</script>
</body></html>`
function App() {
const ref = useRef(null)
return (
<WebView
ref={ref}
html={PAGE_HTML}
onMessage={(msg) => {
console.log('from page:', msg)
ref.current.postMessage('hello from JS')
}}
style={{ flex: 1 }}
/>
)
}Limitations
- Only
postMessagestrings cross the bridge — no shared DOM, no direct JS interop between the host app and the embedded page. - The webview is a real OS child window composited by the platform, not part of Glyx's own GPU render tree — it always renders on top of Glyx content at its screen position, same constraint every framework with a native webview embed has.
allowedOriginsis a navigation allowlist, not a content sandbox — it restricts which origins the page can navigate to, not what the loaded page's own script can do within its origin.