@scopevibe/bridge
v0.1.0
Published
Navigation bridge for Scope — announces client-side navigation events from a web app to the Scope canvas that's embedding it in an iframe.
Downloads
115
Maintainers
Readme
@scopevibe/bridge
Navigation bridge for Scope. Drop it into any web app; Scope's canvas can then embed your app in an iframe and watch client-side navigations happen in real time — turning your prototype into a living flow diagram.
┌────────────── Scope canvas ──────────────┐
│ │
│ ┌────────────┐ ┌────────────┐ │
│ │ /login │ ───▶ │ /dashboard │ │
│ │ [iframe] │ │ [iframe] │ │
│ └────────────┘ └────────────┘ │
│ ▲ │
│ │ postMessage({ scope:navigation }) │
│ │ │
└───────┼──────────────────────────────────┘
│
your deployed app (this library lives inside)Install
npm install @scopevibe/bridge
# or
yarn add @scopevibe/bridge
# or
pnpm add @scopevibe/bridgeQuickstart — Next.js App Router
Drop <ScopeBridge /> into your root layout:
// app/layout.tsx
import { ScopeBridge } from "@scopevibe/bridge/next";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>
<ScopeBridge />
{children}
</body>
</html>
);
}That's it. The component renders nothing on its own — it just attaches
the bridge client-side so every router.push, router.replace, <Link>
click, and browser back/forward fires a scope:navigation postMessage
to the parent window. If your page isn't embedded in an iframe, the
bridge is a no-op.
Quickstart — any framework
import { install } from "@scopevibe/bridge";
install();Call install() once, as early as you can — ideally at the top of your
entry file. It patches history.pushState/replaceState and listens
for popstate/hashchange, so every client-side route change is
captured, regardless of which framework you use.
Works with React Router, SvelteKit, Remix, Vue Router, Solid Router, or
a plain-HTML SPA that moves the URL bar — if history moves, the
bridge sees it.
Quickstart — no build system
Drop the standalone IIFE bundle into a <script> tag:
<script src="https://unpkg.com/@scopevibe/bridge/dist/bridge.global.js"></script>The IIFE auto-installs on load with default options. Nothing else required.
API
install(options?: BridgeOptions): BridgeHandle
Installs the bridge. Safe to call multiple times (re-install is a no-op thanks to a module-level guard).
type BridgeOptions = {
/** Log every bridge action to console. Default: false. */
debug?: boolean;
/** Skip install when the page isn't embedded (window.top === window.self).
* Default: true. Flip to false only for nested-iframe edge cases. */
skipWhenNotEmbedded?: boolean;
};
type BridgeHandle = {
/** Unsubscribe — mostly useful for tests or HMR cleanup. */
detach(): void;
/** Version string announced to the canvas. */
version: string;
};<ScopeBridge /> (Next.js)
import { ScopeBridge } from "@scopevibe/bridge/next";
<ScopeBridge debug={false} />A client component that calls install() in a useEffect. Accepts the
same options as install() as props. Renders null.
BRIDGE_VERSION: string
The version of the bridge protocol this package speaks. Announced in
the scope:ready payload so the canvas can warn about version skew.
Protocol (what the bridge postMessages)
All messages are posted to window.parent with targetOrigin = "*".
The canvas filters by data.type and ignores anything else.
Outbound (your app → Scope canvas)
scope:ready— fires once, right afterinstall(), with the starting URL / pathname / title.scope:navigation— fires on every client-side navigation:pushState,replaceState, back/forward, hash change. Includes areasontag and, when the nav was caused by a click, asourceElementdescriptor so the canvas can anchor its flow arrow to the specific element the user clicked.
Inbound (Scope canvas → your app)
scope:cmd:navigate— the canvas tells your app to navigate to a given pathname without a full reload. The bridge handles this viahistory.pushStatefollowed by a syntheticpopstateso your router picks it up.
Full TypeScript types for every event shape are exported from the main entry.
FAQ
Do I need an account with Scope? Not to run the library — it's just an npm package. You need a Scope canvas to actually see your app as a frame; that's hosted at scope-canvas.pages.dev.
Does it work in production? Yes. The bridge runs in the
client-side bundle of your app and skips itself when the page isn't
embedded (skipWhenNotEmbedded: true by default), so it has zero
effect on direct visitors.
What about CSP / X-Frame-Options? Your deployed app must allow
iframe embedding from the Scope canvas origin. Either leave
X-Frame-Options unset, or set Content-Security-Policy:
frame-ancestors https://scope-canvas.pages.dev (add your dev preview
origin too if you use one).
Will it work with SSR / static export / edge rendering? Yes. The bridge is 100% client-side — it doesn't care how the HTML got there.
How do I debug missing events? Pass debug: true and watch the
iframe's console.
License
MIT — see LICENSE.
