DEV Community

Cover image for Common Third-Party GUI Integration Patterns
Samuel Ruiz
Samuel Ruiz

Posted on

Common Third-Party GUI Integration Patterns

Examples, Code, Pros & Cons

This article covers the most common ways to embed or integrate a third-party UI into your product:

  1. Iframe embed
  2. Script tag / JS SDK
  3. NPM package / component library
  4. Micro-frontend (MFE) integration

Quick Decision Guide

  • Safest, fastest “just embed it”Iframe
  • Quick integration + tight UX (accepts global JS risk)Script tag / JS SDK
  • Best UX + full control + shared design systemNPM package
  • Independent deploys + large teamsMFE

1. Iframe Embed

What it is

You render the third-party UI inside an <iframe> pointing to a URL hosted by the vendor (or another internal team).

Basic Example


html
<iframe
  src="https://vendor.example.com/widget?tenant=acme"
  title="Vendor Widget"
  width="100%"
  height="700"
  style="border:0; border-radius:12px;"
  loading="lazy"
/>
Secure Sandbox Example
html
Copy code
<iframe
  src="https://vendor.example.com/widget?tenant=acme"
  title="Vendor Widget"
  width="100%"
  height="700"
  sandbox="allow-scripts allow-forms allow-popups"
  allow="clipboard-read; clipboard-write"
  style="border:0;"
/>
Parent ↔ Child Communication (postMessage)
Parent

ts
Copy code
const iframe = document.getElementById("vendor-iframe") as HTMLIFrameElement;

window.addEventListener("message", (event) => {
  if (event.origin !== "https://vendor.example.com") return;

  if (event.data?.type === "READY") {
    iframe.contentWindow?.postMessage(
      { type: "SET_THEME", theme: "dark" },
      "https://vendor.example.com"
    );
  }
});
Child

ts
Copy code
window.parent.postMessage({ type: "READY" }, "https://host.example.com");
Pros
Strong isolation (security, CSS, JS)

Easy rollback

Vendor deploys independently

Cons
Styling consistency is harder

Requires postMessage plumbing

SEO & accessibility limitations

Use When
Vendor is untrusted

You want minimal blast radius

Security matters more than UX polish

2. Script Tag / JS SDK
What it is
A vendor-hosted script injects UI or exposes a global SDK.

HTML Example
html
Copy code
<div id="vendor-root"></div>

<script src="https://cdn.vendor.com/widget/v1/widget.min.js"></script>
<script>
  VendorWidget.mount("#vendor-root", {
    tenant: "acme",
    theme: "light",
  });
</script>
React Wrapper Example
tsx
Copy code
import { useEffect, useRef } from "react";

export function VendorWidget({ tenant }: { tenant: string }) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const instance = (window as any).VendorWidget.mount(ref.current, { tenant });
    return () => instance?.unmount?.();
  }, [tenant]);

  return <div ref={ref} />;
}
Pros
Faster than iframe for UX

Easy to integrate

No build-time dependency

Cons (Real Risks)
Executes untrusted JS in your origin

CSS/global JS conflicts

Debugging is painful

Version drift via CDN

Required Safety Measures
Pin versions

Use SRI (integrity)

Lock down CSP

Demand namespaced CSS or Shadow DOM

Use When
Vendor is trusted

Widget is small

You need fast integration

3. NPM Package / Component Library
What it is
You install the vendor UI as a dependency and render components directly.

Install
bash
Copy code
npm install @vendor/ui @vendor/sdk
React Example
tsx
Copy code
import { VendorCheckout } from "@vendor/ui";

export function Checkout() {
  return (
    <VendorCheckout
      customerId="cust_123"
      theme="light"
      onSuccess={(r) => console.log(r)}
    />
  );
}
Pros
Best UX integration

Fully testable

Explicit version control

Styling consistency

Cons
Bundle size impact

Dependency conflicts

Vendor bugs break builds

No isolation

Best Practices
Pin exact versions

Lazy-load heavy UI

Wrap vendor UI with an adapter layer

Use When
UI is core to your product

You control UX and design

You accept ownership of upgrades

4. Micro-Frontend (MFE)
What it is
A separately built and deployed frontend loaded at runtime.

Host Loader Example
ts
Copy code
async function loadRemote(url: string) {
  await new Promise<void>((resolve) => {
    const s = document.createElement("script");
    s.src = url;
    s.onload = () => resolve();
    document.head.appendChild(s);
  });

  return (window as any).RemoteApp;
}

const remote = await loadRemote("https://cdn.example.com/remote.js");
const instance = remote.mount(document.getElementById("root"), { tenant: "acme" });
Remote App Contract
ts
Copy code
export function mount(el: Element, opts: { tenant: string }) {
  // render app
  return { unmount() {} };
}

(window as any).RemoteApp = { mount };
Pros
Independent deploys

Scales across teams

Shared runtimes possible

Cons
High complexity

Version coordination issues

Harder observability

Slower local dev

Use When
Multiple teams

Independent release cycles

Large surface-area UI

Comparison Table
Pattern Isolation   UX  Complexity  Risk
Iframe  High    Medium  Low Low
Script / SDK    Low High    Low Medium-High
NPM Library Low Very High   Medium  Medium
MFE Medium  High    High    Medium

Critical Engineering Concerns
Authentication
Avoid long-lived tokens in URLs

Prefer short-lived session tokens

Never expose secrets to iframe URLs

Styling
Use tokens or theme contracts

Avoid global CSS leaks

Prefer Shadow DOM when possible

Performance
Lazy load everything non-critical

Cache remote assets

Watch duplicate bundles (MFE)

Reliability
Loading states

Timeouts

Graceful fallbacks (link-out)

Practical Recommendations
Untrusted vendor → Iframe

Trusted widget → Script SDK (with CSP + SRI)

Core product UI → NPM library

Large org / many teams → MFE (with platform investment)

Alternative Approaches
Web Components

OAuth-style redirect flows

Vendor-hosted portals with callbacks

Bottom line:
Isolation buys safety. Tight integration buys UX. Complexity grows fast.
Choose the least powerful integration that still solves the problem.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)