@launchmystore/app-bridge
v1.0.3
Published
LaunchMyStore App Bridge SDK — postMessage-based communication between app iframes and the LaunchMyStore admin host. Dispatch Toast, Modal, ResourcePicker, TitleBar, NavigationMenu, SessionToken and 15+ other action families.
Downloads
676
Maintainers
Readme
@launchmystore/app-bridge
Vanilla JavaScript / TypeScript SDK for LaunchMyStore
apps. Lets your iframe-embedded app communicate with the LMS admin host
(toasts, modals, resource pickers, session tokens, redirects, and more)
over postMessage.
Framework-agnostic. If you're using React, install
@launchmystore/app-bridge-react
instead — it wraps this SDK in hooks.
About LaunchMyStore
LaunchMyStore is a multi-tenant e-commerce
platform that renders Shopify-compatible Liquid themes and runs a full
app ecosystem on top of them. Merchants get a branded storefront on a
custom domain; developers ship apps that extend the storefront,
checkout, and admin via the same Apps row, OAuth scopes, webhooks,
and declarative function manifests. This SDK is the bridge between
your app's iframe and the LMS admin shell.
Learn more: launchmystore.io · Docs: docs.launchmystore.io
Installation
npm install @launchmystore/app-bridgeQuick Start
import { createApp, Toast, Modal } from '@launchmystore/app-bridge';
const app = createApp({
apiKey: 'your-app-api-key',
host: window.__LMS_HOST__, // base64-encoded admin origin, injected by host
});
// Show a toast
const toast = Toast.create(app, { message: 'Saved!', duration: 3000 });
toast.dispatch(Toast.Action.SHOW);
// Make an authenticated API call
const token = await app.getSessionToken();
const res = await fetch('/api/v1/products.json', {
headers: { Authorization: `Bearer ${token}` },
});Core API
createApp(config)
Creates an App instance and starts listening for messages from the host.
const app = createApp({
apiKey: string, // your app's API key
host: string, // base64-encoded host origin (injected as ?host= query param)
});app.dispatch(action, payload)
Fire-and-forget message to the host. Returns a message id.
app.dispatch('TOAST_SHOW', { message: 'Hello', duration: 3000 });app.dispatchAndWait(action, payload)
Dispatch and await the host's response. Rejects on error or after a 10s timeout.
const { selection } = await app.dispatchAndWait('RESOURCE_PICKER_OPEN', {
resourceType: 'product',
multiple: true,
});app.subscribe(action, callback)
Subscribe to broadcast actions from the host (e.g. LIFECYCLE_EVENT,
HISTORY_POP). Returns an unsubscribe function.
const unsubscribe = app.subscribe('LIFECYCLE_EVENT', (payload) => {
console.log('Lifecycle:', payload.event);
});app.getSessionToken()
Returns a short-lived JWT for authenticated calls to /api/v1/*.
const token = await app.getSessionToken();app.redirect.dispatch({ url, newContext })
Navigate within the admin shell. Set newContext: true to open in a new tab.
app.redirect.dispatch({ url: '/products' });app.destroy()
Remove the message listener and clear pending callbacks. Call on unmount.
Available Actions
All actions live under their namespaced exports and follow the
Action.create(app, options) pattern.
UI
Toast— success / error / warning / info notificationsModal— full or sheet modals with primary/secondary actionsTitleBar— admin title bar actions + breadcrumbsNavigationMenu— app sidebar menu itemsContextualSaveBar— sticky save/discard barLoading— global loading indicator
Pickers & dialogs
ResourcePicker— pick from 11 resource types (product, variant, collection, customer, order, blog, article, page, menu, file, metaobject)LeaveConfirmation— block navigation with a confirm dialogScanner— barcode / QR code scanner
Navigation & lifecycle
Redirect— admin or external navigationHistory— replace / push state inside the iframeLifecycle— install / uninstall / app-config eventsFullscreen— request / exit fullscreen mode
Data APIs
User— current admin userConfig— shop config, plan, feature flagsEnvironment— runtime environment infoFeatures— which App Bridge features the host implementsSessionToken— JWT for authenticated REST callsRestApi— fetch wrapper that auto-attaches the session token
Browser
Print— triggerwindow.print()on the hostShare— Web Share API proxyClipboard— read/write the system clipboard (must go through host in cross-origin iframes)
Storefront / checkout
Cart— read cart state, apply line / metafield changesBuyerJourney— intercept checkout steps (post-purchase, checkout extensions)I18n— locale + translation state
Cross-extension
Intents— launch other extensions by intent (e.g. open Reviews extension from Products page)
Examples
Modal with primary action
import { createApp, Modal } from '@launchmystore/app-bridge';
const app = createApp({ apiKey, host });
const modal = Modal.create(app, {
title: 'Confirm import',
message: 'Import 1,200 products from Shopify?',
primaryAction: {
content: 'Import',
onAction: async () => {
await runImport();
modal.dispatch(Modal.Action.CLOSE);
},
},
secondaryActions: [{ content: 'Cancel' }],
});
modal.dispatch(Modal.Action.OPEN);Resource picker
import { createApp, ResourcePicker } from '@launchmystore/app-bridge';
const app = createApp({ apiKey, host });
const picker = ResourcePicker.create(app, {
resourceType: ResourcePicker.ResourceType.Product,
multiple: true,
});
picker.subscribe(ResourcePicker.Action.SELECT, ({ selection }) => {
console.log('Picked', selection);
});
picker.dispatch(ResourcePicker.Action.OPEN);Session token + authenticated fetch
import { createApp } from '@launchmystore/app-bridge';
const app = createApp({ apiKey, host });
async function authedFetch(path, init = {}) {
const token = await app.getSessionToken();
return fetch(path, {
...init,
headers: { ...(init.headers || {}), Authorization: `Bearer ${token}` },
});
}
const res = await authedFetch('/api/v1/orders.json');
const { orders } = await res.json();Contextual save bar
import { createApp, ContextualSaveBar } from '@launchmystore/app-bridge';
const app = createApp({ apiKey, host });
const saveBar = ContextualSaveBar.create(app, {
saveAction: { onAction: handleSave },
discardAction: { onAction: handleDiscard },
});
function onFormDirty() {
saveBar.dispatch(ContextualSaveBar.Action.SHOW);
}
function onFormClean() {
saveBar.dispatch(ContextualSaveBar.Action.HIDE);
}TypeScript
Full type definitions ship with the package — no @types/* install
required.
import type {
AppConfig,
AppBridgeMessage,
AppBridgeResponse,
ToastOptions,
ModalOptions,
ResourcePickerOptions,
ResourceType,
} from '@launchmystore/app-bridge';Wire format
Iframe → host:
{ "type": "APP_BRIDGE_ACTION", "action": "TOAST_SHOW", "id": "ab_…", "payload": { … } }Host → iframe:
{ "type": "APP_BRIDGE_RESPONSE", "action": "TOAST_SHOW", "id": "ab_…", "payload": { … } }The host validates event.origin against the registered redirect URLs;
the SDK validates event.origin against the decoded host config.
License
MIT
