Riftix Console Bridge

Getting Started

Set up the Riftix Console Bridge end to end in five minutes.

Prerequisites

  • pnpm 10+, Node 22+
  • A host app (the shell — e.g. apps/console): React + Vite or any framework that can render <iframe> elements.
  • A client app (a product page embedded inside the host): any stack that can include a <script> tag.

1. Host setup

Install

pnpm add @riftix/console-bridge-host

Wrap your app in ConsoleHostProvider

import { ConsoleHostProvider } from "@riftix/console-bridge-host/react";

export function App() {
  return (
    <ConsoleHostProvider
      defaultContextProvider={() => ({ theme: "light", locale: "en-US" })}
      defaultAuthorizationProvider={(channel) => ({
        clientId: channel.productId,
        organizationId: "org_123",
        token: "jwt.goes.here",
        expiresAt: Date.now() + 3_600_000,
      })}
    >
      {/* your routes / shell */}
    </ConsoleHostProvider>
  );
}

Render an iframe

import { ConsoleIframe } from "@riftix/console-bridge-host/react";

export function BillingPage() {
  return (
    <ConsoleIframe
      src="https://billing.example.com"
      origin="https://billing.example.com"
      productId="billing"
      style={{ width: "100%", height: "100%", border: "none" }}
    />
  );
}

Handle RPCs from client products

import { useConsoleHost } from "@riftix/console-bridge-host/react";
import { toast } from "sonner";

function ToastHandler() {
  const host = useConsoleHost();

  useEffect(() => {
    return host.handle("toast.show", ({ message, variant }) => {
      toast[variant ?? "info"](message);
    });
  }, [host]);

  return null;
}

2. Client setup

The client page is loaded inside the host <iframe>. The only distribution is the IIFE snippet — there is no npm client package.

Load the snippet

Add to your index.html:

<!-- Tell the snippet which origin to accept messages from -->
<meta name="riftix-host" content="https://console.example.com" />

<!-- Load the snippet from the host's snippet dev server or CDN -->
<script src="https://console.example.com/riftix.js"></script>
pnpm add -D @riftix/console-bridge-snippet-types

Then in any .ts / .tsx file (or in tsconfig.json > types):

import "@riftix/console-bridge-snippet-types";
// window.Riftix is now typed

Wait for the bridge and call APIs

await window.Riftix!.ready;

window.Riftix!.toast.show({ message: "Hello from billing!", variant: "success" });

const confirmed = await window.Riftix!.modal.confirm({
  title: "Delete invoice?",
  body: "This cannot be undone.",
  confirmLabel: "Delete",
  cancelLabel: "Cancel",
  destructive: true,
});

React hooks

pnpm add @riftix/console-bridge-snippet-react
import { useRiftixContext, useRiftixAuthorization } from "@riftix/console-bridge-snippet-react";

function Dashboard() {
  const { status, context } = useRiftixContext();
  const auth = useRiftixAuthorization();

  if (status === "loading") return <p>Connecting…</p>;

  return (
    <div>
      <p>Theme: {context.theme}</p>
      <p>Token: {auth?.token ?? "none"}</p>
    </div>
  );
}

Declarative breadcrumbs

Instead of calling Riftix.navigation.setBreadcrumbs() imperatively, use the built-in web components:

<riftix-page>
  <riftix-breadcrumb href="/billing">Billing</riftix-breadcrumb>
  <riftix-breadcrumb>Invoices</riftix-breadcrumb>
</riftix-page>

The host navbar updates live as the DOM changes. See Web Components for full details.


3. Running the demo

The monorepo ships with a full working demo.

# From repo root — builds packages then starts all dev servers
bun run dev
URLWhat it is
http://localhost:6173console shell
http://localhost:6174demo-client (billing product)
http://localhost:6175snippet dev server

Open http://localhost:6173/billing. The billing iframe loads, the bridge handshakes, and breadcrumbs in the host navbar update when you switch sections inside the iframe.

On this page