Riftix Console Bridge

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 ready messages from the declared origin, and sends hello to that origin. Strongly recommended in production.
  • Absent: the snippet accepts the first ready from any origin and locks onto it.

Bootstrap rules

  • No-op if window.Riftix already 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

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>
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): () => void

The 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-types

Then 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();

On this page