Embed Chat with DIAL Overlay
In this tutorial, you will embed DIAL Chat in a static HTML page using the DIAL Overlay library. By the end, you will have a host page that loads Chat in an iframe, sends a message programmatically, and listens for generation events.
Prerequisites
- A running DIAL instance with DIAL Chat
- Node.js 18+ installed
- Basic familiarity with HTML and TypeScript
What you will build
A minimal web page that embeds DIAL Chat as an overlay widget. The host page will:
- Display DIAL Chat in a wide iframe
- Send a message to the active conversation via the Overlay API
- Log an event to the browser console when the model starts generating
Project structure
By the end of this tutorial, your project will look like this:
dial-overlay-demo/
├── package.json
├── index.html
└── src/
└── main.ts
Step 1: Configure DIAL Chat for overlay mode
Add the following environment variables to your DIAL Chat deployment. If you use Docker Compose, update the chat service in your docker-compose.yml:
chat:
image: epam/ai-dial-chat:0.41.7
platform: linux/amd64
environment:
IS_IFRAME: "true"
ALLOWED_IFRAME_ORIGINS: "http://localhost:5173"
ALLOW_OPEN_SIGNIN_PAGE_IN_IFRAME: "true"
ALLOWED_IFRAME_ORIGINS must match the origin where your host page will run. The Vite dev server used later in this tutorial defaults to http://localhost:5173.
Restart the Chat container after changing the configuration.
Verify: DIAL Chat starts without errors. Open http://localhost:3000 in a browser—Chat loads normally, but it is now also available for iframe embedding.
Step 2: Scaffold the host project
Create a new directory and initialize a Node.js project:
mkdir dial-overlay-demo && cd dial-overlay-demo
npm init -y
Install the Overlay library and a development server:
npm install @epam/ai-dial-overlay@0.9.0
npm install --save-dev vite@6.3.5 typescript@5.8.3
Verify: node_modules/@epam/ai-dial-overlay exists and package.json lists both dependencies.
Step 3: Create dial-overlay-demo/index.html
Create dial-overlay-demo/index.html with a container element for the overlay:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>DIAL Overlay Demo</title>
<style>
#chat-container {
width: 100%;
height: 600px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<h1>DIAL Overlay Demo</h1>
<div id="chat-container"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Step 4: Create dial-overlay-demo/src/main.ts
Create dial-overlay-demo/src/main.ts with the Overlay initialization logic:
import { ChatOverlay } from '@epam/ai-dial-overlay';
const container = document.getElementById('chat-container');
if (!container) {
throw new Error('Container element not found');
}
const overlay = new ChatOverlay(container, {
hostDomain: window.location.origin,
domain: 'http://localhost:3000', // your DIAL Chat overlay instance
theme: 'light',
modelId: 'gpt-4o', // replace with a model deployed in your DIAL instance
});
await overlay.ready();
console.log('Overlay is ready');
This creates an iframe inside the container, waits for the DIAL Chat handshake to complete, and logs a message to the console.
Verify: No verification yet—the dev server is not running. Continue to step 5.
Step 5: Start the dev server and verify the overlay
Start the Vite development server:
npx vite
Open http://localhost:5173 in a browser.
Verify: The page displays the heading "DIAL Overlay Demo" and an embedded DIAL Chat interface inside the bordered container. The browser console shows Overlay is ready.
Step 6: Send a message programmatically
Add the following lines to dial-overlay-demo/src/main.ts, after the await overlay.ready() call:
const sendButton = document.createElement('button');
sendButton.textContent = 'Send greeting';
sendButton.addEventListener('click', async () => {
await overlay.sendMessage('Hello from the host application!');
console.log('Message sent');
});
document.body.insertBefore(sendButton, container);
Verify: Reload the page. Click the "Send greeting" button. The message "Hello from the host application!" appears in the embedded Chat conversation, and the model responds. The console shows Message sent.
Step 7: Subscribe to generation events
Add the following lines to dial-overlay-demo/src/main.ts, after the button code:
const unsubscribe = overlay.subscribe(
'@DIAL_OVERLAY/GPT_START_GENERATING',
() => {
console.log('Model started generating a response');
}
);
Verify: Reload the page and send a message. The browser console shows Model started generating a response each time the model begins generating.
Step 8: Retrieve conversation messages
Add the following lines to dial-overlay-demo/src/main.ts:
const fetchButton = document.createElement('button');
fetchButton.textContent = 'Get messages';
fetchButton.addEventListener('click', async () => {
const { messages } = await overlay.getMessages();
console.log('Conversation messages:', messages);
});
document.body.insertBefore(fetchButton, container);
Verify: Click "Get messages" after a conversation exchange. The browser console logs an array of message objects from the active conversation.
What you learned
- How to configure DIAL Chat for overlay mode using
IS_IFRAMEandALLOWED_IFRAME_ORIGINS - How to create a
ChatOverlayinstance and wait for the iframe handshake - How to send messages and retrieve conversation history programmatically
- How to subscribe to overlay events
Further reading
- DIAL Overlay overview — learn about
ChatOverlayManagerfor multi-instance setups, all configuration options, and layout variants - Theming and design — customize the color scheme and branding of the embedded Chat
- How DIAL Chat is configured — how Chat reads environment variables and where each group is documented
- Embed AI in existing tools — reaching users inside Teams, Excel, and automation tools
- Overlay sandbox examples — explore more advanced integration patterns in the upstream repository