Storybook Integration
Use the Storybook entrypoint when Itera should load a Storybook manager URL such as http://127.0.0.1:6006/?path=/story/... instead of a direct iframe.html story URL.
This is the validated React Storybook flow: the manager window relays inspector traffic into the active preview iframe, while the preview bridge and iteration runtime stay inside the preview surface.
What this supports
- preview-only inspection for React Storybook previews
- Storybook manager URLs without host-side
iframe.htmlURL rewriting - direct
iframe.htmlfallback when you intentionally want to bypass the manager relay
Out of scope:
- inspecting Storybook manager panels, toolbars, or addon UI
- support claims beyond the React Storybook 10 manager/preview contract validated in
itera_design_system
Install
The Storybook helpers ship in the same React package:
npm install @iteraai/react-component-inspector @iteraai/inspector-protocol react react-dom1. Add a shared preview bootstrap
Read the base Itera host allowlist from VITE_ITERA_COMPONENT_INSPECTOR_HOST_ORIGINS, then derive the Storybook manager origin from the preview referrer. When the preview is loaded directly through iframe.html, the resolver falls back to the explicit allowlist from that env var.
import { bootIterationInspectorRuntime } from '@iteraai/react-component-inspector/iterationInspector';
import {
bootstrapStorybookPreviewInspectorBridge,
resolveStorybookPreviewHostOrigins,
} from '@iteraai/react-component-inspector/storybook';
const COMPONENT_INSPECTOR_LOG_PREFIX = '[itera/storybook/component-inspector]';
const STORYBOOK_COMPONENT_INSPECTOR_BOOTSTRAPPED_FLAG =
'__ITERA_STORYBOOK_COMPONENT_INSPECTOR_BOOTSTRAPPED__';
export const STORYBOOK_COMPONENT_INSPECTOR_HOST_ORIGINS =
import.meta.env.VITE_ITERA_COMPONENT_INSPECTOR_HOST_ORIGINS;
type GlobalState = typeof globalThis & {
[STORYBOOK_COMPONENT_INSPECTOR_BOOTSTRAPPED_FLAG]?: boolean;
};
const globalState = globalThis as GlobalState;
export const bootstrapStorybookComponentInspector = () => {
if (globalState[STORYBOOK_COMPONENT_INSPECTOR_BOOTSTRAPPED_FLAG] === true) {
return false;
}
try {
const previewHostOrigins = resolveStorybookPreviewHostOrigins({
hostOrigins: STORYBOOK_COMPONENT_INSPECTOR_HOST_ORIGINS,
referrer: document.referrer || undefined,
});
bootIterationInspectorRuntime();
const bridge = bootstrapStorybookPreviewInspectorBridge({
enabled: true,
hostOrigins: previewHostOrigins,
});
globalState[STORYBOOK_COMPONENT_INSPECTOR_BOOTSTRAPPED_FLAG] = true;
window.addEventListener(
'beforeunload',
() => {
bridge.destroy();
},
{ once: true },
);
return true;
} catch (error) {
console.error(
`${COMPONENT_INSPECTOR_LOG_PREFIX} Failed to bootstrap the Storybook preview inspector.`,
error,
);
return false;
}
};2. Start the manager relay once
Boot the relay from .storybook/manager.ts so the manager window can forward both itera-component-inspector and itera:iteration-inspector traffic to the active preview iframe.
import { initStorybookManagerRelay } from '@iteraai/react-component-inspector/storybook';
import { STORYBOOK_COMPONENT_INSPECTOR_HOST_ORIGINS } from './storybook-bootstrap';
const COMPONENT_INSPECTOR_LOG_PREFIX = '[itera/storybook/component-inspector]';
const STORYBOOK_MANAGER_RELAY_BOOTSTRAPPED_FLAG =
'__ITERA_STORYBOOK_MANAGER_RELAY_BOOTSTRAPPED__';
type GlobalState = typeof globalThis & {
[STORYBOOK_MANAGER_RELAY_BOOTSTRAPPED_FLAG]?: boolean;
};
const globalState = globalThis as GlobalState;
if (globalState[STORYBOOK_MANAGER_RELAY_BOOTSTRAPPED_FLAG] !== true) {
try {
initStorybookManagerRelay({
hostOrigins: STORYBOOK_COMPONENT_INSPECTOR_HOST_ORIGINS,
});
globalState[STORYBOOK_MANAGER_RELAY_BOOTSTRAPPED_FLAG] = true;
} catch (error) {
console.error(
`${COMPONENT_INSPECTOR_LOG_PREFIX} Failed to bootstrap the Storybook manager relay.`,
error,
);
}
}initStorybookManagerRelay(...) targets the Storybook 10 preview iframe selector iframe#storybook-preview-iframe by default. If your Storybook shell replaces or wraps that iframe, pass previewIframeSelector or resolvePreviewIframe.
3. Call the preview bootstrap from .storybook/preview.tsx
Start the preview wrapper at module load so the runtime and preview bridge are ready before stories become interactive.
import { bootstrapStorybookComponentInspector } from './storybook-bootstrap';
void bootstrapStorybookComponentInspector();Notes
- Keep
VITE_ITERA_COMPONENT_INSPECTOR_HOST_ORIGINSlimited to exact Itera host origins. The preview resolver adds the Storybook manager origin intentionally; do not replace the explicit host allowlist with the Storybook origin. - If
document.referreris missing or rewritten in your preview, passmanagerOriginexplicitly toresolveStorybookPreviewHostOrigins(...)orbootstrapStorybookPreviewInspectorBridge(...). - For non-Storybook React apps, stay on the standard React integration.