Snippet Overview
The window.Riftix global installed by riftix.js.
The snippet (riftix.js) is a self-contained IIFE bundle. It installs window.Riftix and registers the <riftix-page> / <riftix-breadcrumb> web components. There is no npm package for the client — the IIFE is the only distribution.
Loading the snippet
<head>
<!-- Restrict which host origin is trusted -->
<meta name="riftix-host" content="https://console.example.com" />
</head>
<body>
<!-- Load from the host's snippet dev server or CDN -->
<script src="https://console.example.com/riftix.js"></script>
</body><meta name="riftix-host">
- Present: the snippet only accepts
readymessages from the declared origin, and sendshelloto that origin. Strongly recommended in production. - Absent: the snippet accepts the first
readyfrom any origin and locks onto it.
Bootstrap rules
- No-op if
window.Riftixalready exists (idempotent). - No-op if the page is not inside an iframe (
window.parent === window). Safe to include on standalone pages. - No-op in non-browser environments (
typeof window === "undefined").
window.Riftix
interface Riftix {
/** Live getter — current HostContext or null before handshake. */
readonly context: HostContext | null;
/** Live getter — current authorization or null. */
readonly authorization: BridgeAuthorization | null;
/**
* Resolves after the handshake completes AND the first
* `authorization:changed` event is received (even if null).
*/
readonly ready: Promise<void>;
toast: RiftixToastNamespace;
modal: RiftixModalNamespace;
navigation: RiftixNavigationNamespace;
events: RiftixEventsNamespace;
/** Tears down the bridge and deletes window.Riftix. */
dispose(): void;
}Namespaces
navigation
Riftix.navigation.navigate(payload: { to: string; replace?: boolean }): Promise<void>
Riftix.navigation.setTitle(payload: { title: string; subtitle?: string }): Promise<void>
Riftix.navigation.setBreadcrumbs(payload: { crumbs: ReadonlyArray<BridgeBreadcrumb> }): Promise<void>
/**
* Internal — called automatically by the snippet's location-sync layer.
* Reports the current iframe URL to the host whenever the URL changes.
* You do not need to call this manually.
*/
Riftix.navigation.locationChanged(payload: { path: string }): Promise<void>toast
Riftix.toast.show(payload: {
message: string;
variant?: "info" | "success" | "warning" | "error";
durationMs?: number;
}): Promise<void>modal
Riftix.modal.confirm(payload: {
title: string;
body: string;
confirmLabel?: string;
cancelLabel?: string;
destructive?: boolean;
}): Promise<boolean>events
Riftix.events.on<E extends BridgeEventName>(
event: E,
handler: (payload: BridgeEventPayload<E>) => void
): () => void // returns unsubscribe function
Riftix.events.onContextChanged(handler: (context: HostContext) => void): () => void
Riftix.events.onAuthorizationChanged(handler: (auth: BridgeAuthorization | null) => void): () => void
// Navigation:
Riftix.events.onNavigate(handler: (payload: { path: string; replace?: boolean }) => void): () => voidThe navigation:navigate event is handled automatically by the snippet's location-sync layer — setupLocationSync subscribes internally and updates the iframe's history. You only need onNavigate if you want to run custom logic in addition to (or instead of) the automatic handling.
TypeScript types
Install the types package as a dev dependency:
pnpm add -D @riftix/console-bridge-snippet-typesThen import it once as a side-effect (anywhere in your project, or via tsconfig.json > "types"):
import "@riftix/console-bridge-snippet-types";This augments Window with Riftix?: Riftix, adds JSX IntrinsicElements for the web components, and adds HTMLElementTagNameMap entries so querySelector is typed.
Usage pattern
// Await the bridge before calling any API
await window.Riftix!.ready;
// Synchronous snapshot reads (safe after ready)
const { theme } = window.Riftix!.context!;
const token = window.Riftix!.authorization?.token;
// RPC call
await window.Riftix!.toast.show({ message: "Saved!", variant: "success" });
// Subscribe to events
const unsub = window.Riftix!.events.onContextChanged((ctx) => {
document.documentElement.classList.toggle("dark", ctx.theme === "dark");
});
// Later: unsub();