Skip to content
OpenDIL
GitHub☆ 2

Getting started

OpenDIL renders a growing text response as an interactive React interface. Your application supplies the source; the document can contain Markdown, controls, charts, and its own state.

Use React 19.

Terminal window
npm install @snackbit/opendil react react-dom

For the default iframe isolation mode (mode="isolated"), also copy the runtime assets. The asset CLI requires Node 22 or newer:

Terminal window
npx opendil copy-assets --out public/opendil

Serve the copied opendil directory with your application. The iframe renderer loads its sandboxed frame from /opendil/frame.html. Copy these assets again when you upgrade the package.

Host (mode="host") and Shadow DOM (mode="shadow") modes do not require copy-assets. Their runtime code and workers are bundled with your application.

Answer.tsx
import { DilRenderer } from "@snackbit/opendil";
import "@snackbit/opendil/styles.css";
export function Answer() {
return <DilRenderer text="<title>Hello, interface.</title>" />;
}

Document state lives in a bounded QuickJS worker. A control updates that state, and expressions supply the next values to the interface.

DIL source
{@body const [name, setName] = DIL.useState("Ada")}
{@body const [notifications, setNotifications] = DIL.useState(true)}
<box border padding={5} radius="xl" gap={4}>
<title size="xl">Make yourself at home.</title>
<label>Display name</label>
<input
aria-label="Display name"
value={name}
onChange={setName}
/>
<checkbox checked={notifications} onChange={setNotifications}>
Send me release updates
</checkbox>
<box
background="surface-secondary"
radius="lg"
padding={4}
gap={2}
>
<title>Welcome, {name || "friend"}.</title>
<text color="secondary">Release updates are {notifications ? "on" : "off"}.</text>
</box>
</box>
<DilRenderer
key={messageId}
text={sourceReceivedSoFar}
isStreaming={receiving}
/>

Append to the existing source prefix. Set isStreaming={false} after the final chunk. Use a new key to replace, edit, or restart a document. The renderer does not connect to a model provider or own your network transport.

Read Streaming for reveal, update cadence, and scroll following.

runtimeBaseUrl applies only to iframe mode. For an application hosted below a subpath, point to the matching runtime directory:

<DilRenderer text={source} runtimeBaseUrl="/my-app/opendil/" />

Keep the runtime assets and npm package on the same version. See Isolation for Shadow DOM and host rendering, and Customization for your own components and theme.