Build a component. Render it anywhere.
Export a React component. One command builds it to a single HTML file. Import that file in another app and render it like any other component, sandboxed in its own frame.
- 1
Export a component
A React component, default export. Props come from the host.
rating.tsx type Props = { value?: number; onRate: (n: number) => Promise<void>; }; export default function Rating({ value = 0, onRate, }: Props) { return ( <div className="stars"> {[1, 2, 3, 4, 5].map((n) => ( <button key={n} onClick={() => onRate(n)}> {n <= value ? "★" : "☆"} </button> ))} </div> ); } - 2
Build it to one file
React, your code, CSS and the runtime in one HTML file. No config.
terminal $ npx remote-components build rating.tsx dist/rating.html - 3
Import it in another app
Pass the file to RemoteComponent. Callbacks are async functions.
App.tsx import { useState } from "react"; import { RemoteComponent, } from "@assistant-ui/remote-components-host-react"; import rating from "widgets/dist/rating.html?raw"; export function Review() { const [stars, setStars] = useState(3); return ( <RemoteComponent html={rating} value={stars} onRate={async (n) => setStars(n)} /> ); }
Plain HTML underneath
The build output is an ordinary HTML page with one script in it. So any page works: a hand-written fragment, a page a model wrote, any built app. Pass it inline with html, or serve it and point src at the URL.
<h3>Weather in <span id="city">Berlin</span></h3>
<button>Monday</button>
<script>
rc.addEventListener("props-changed", () => (city.textContent = rc.props.city));
document.querySelector("button").onclick = () => rc.props.onSelect("mon");
</script><RemoteComponent
src="https://widgets.example/weather.html"
city="Lisbon"
onSelect={async (day) => setDay(day)}
/>Laid out inline
The frame sizes to its content and takes your theme. Popovers and dialogs render on your page, outside the frame.
Nov 6
Isolation, set from outside
The remote is untrusted code. Sandbox, origin and network are set by your page and the server.
Its own origin
The iframe can't read your DOM, cookies or storage. Generated HTML runs on an opaque origin.
Network you control
Remotes call public APIs directly, without your cookies. Turn it off with network="none", or allow a list of origins.
Data across the boundary
Props and arguments are structured-clone data. Functions only go one way, as props.
Safe Content Frames
For code you don't trust, each publisher gets a hashed origin on a public-suffix domain.