@gnome-ui/platform
v1.28.0
Published
TypeScript API layer for communicating with the GNOME host process from a React app
Readme
@gnome-ui/platform
TypeScript API layer for communicating with the GNOME host process from a React app running inside a WebKitGTK WebView.
Status: work in progress — API surface is defined, implementations are pending.
How it works
@gnome-ui/platform communicates with the GNOME host process through one
of two mechanisms, resolved at runtime:
| Environment | Bridge |
| --- | --- |
| WebKitGTK WebView (GJS host) | window.webkit.messageHandlers.* |
| Flatpak / sandboxed app | XDG Desktop Portals |
| Browser / test | no-op stubs (never throws) |
Installation
npm install @gnome-ui/platformModules
| Module | Description |
| --- | --- |
| settings | Read/write application settings via GSettings |
| notifications | Send and withdraw desktop notifications (Gio.Notification) |
| fileChooser | Open/save file dialogs (GtkFileChooserDialog / XDG portal) |
| colorScheme | Detect and change the Adwaita color scheme (light/dark/auto) |
| window | Query and change window state (maximize, minimize, fullscreen) |
| clipboard | Read and write the GDK clipboard (text, files, images) |
| portals | Low-level XDG Desktop Portal access for Flatpak apps |
| hapticFeedback | Trigger haptic feedback via feedbackd; falls back to Vibration API in browser/PWA |
Bridge utilities
Web → Native
Send messages from the web layer to a named GJS handler:
import { isWebKitBridge, postMessage } from "@gnome-ui/platform";
if (isWebKitBridge()) {
console.log("Running in GNOME app context");
}
await postMessage("notifications", { title: "Hello", body: "World" });Native → Web events
Subscribe to events dispatched by the GJS host. The host fires them by
evaluating a CustomEvent in the WebView:
// GJS side — dispatch an event to the web layer
webView.evaluate_javascript(
`window.dispatchEvent(new CustomEvent("gnome:open-modal", { detail: { id: "settings" } }))`,
-1, null, null, null, null
);// Web side — subscribe (returns an unsubscribe function)
import { onNativeEvent } from "@gnome-ui/platform";
const off = onNativeEvent("open-modal", (payload) => {
console.log("open modal:", payload.id);
});
// later, clean up:
off();All native events use the gnome: prefix internally — pass only the
unprefixed name to onNativeEvent.
Runtime detection
import { getRuntime } from "@gnome-ui/platform";
const { shell, engine, browser, os } = getRuntime();
if (shell === "webkitgtk-webview") // running inside a GNOME native app
if (shell === "pwa") // installed PWA
if (browser.epiphany) // running inside GNOME Web (Epiphany)
if (os.linux) // Linux host