@helpai/elements
v1.3.11
Published
Help AI embeddable AI agent elements for the browser. Six chat layouts (floating / inline / modal / drawer / page / standalone) plus an iframe wrapper. Shadow-DOM-isolated, streaming SSE.
Downloads
9,813
Maintainers
Readme
Help AI Elements
Embeddable AI agent elements for help.ai. A library of browser elements — Web Components and a programmatic API — that drop your AI agent into any website. Six layout variations of the chat element ship today (floating launcher, inline block, modal, drawer, full-page, standalone) plus an iframe wrapper for strict isolation. Shadow-DOM-isolated, streaming SSE, zero React in the bundle.
Full documentation: https://help.ai/docs/elements
This README is a quick-start. Configuration reference, theming, lifecycle hooks, framework recipes, and the backend contract live on the docs site.
Identity
Every element requires aiAgentDeploymentId. Add its deployment publicKey
for the normal browser-authenticated mount; omit only publicKey for an
intentional guest deployment. The publicKey + secretKey flow is server-to-server
only (API SDK) — never use a secret in browser code.
Install
CDN (one-line script tag)
<script
src="https://cdn.help.ai/elements/latest/elements.js"
data-public-key="agent_pk_..."
data-ai-agent-deployment-id="..."
defer
></script>Boots the floating launcher in the bottom-right of the page. No further setup needed.
NPM
npm install @helpai/elementsimport { mount } from "@helpai/elements";
const agent = mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: document.getElementById("chat"),
});
agent.on("message", (m) => console.log(m));Web Component
<script type="module" src="https://cdn.help.ai/elements/latest/elements.js"></script>
<web-ai-chat
public-key="agent_pk_..."
ai-agent-deployment-id="..."
mode="inline"
style="display: block; height: 600px"
></web-ai-chat>The custom element observes attribute changes — flip mode, theme,
position, public-key, or ai-agent-deployment-id and the element
re-resolves at runtime.
Build catalog — every release ships every format
| File | Format | Use with |
| --------------------------------- | ------ | ---------------------------------------------- |
| elements.js | IIFE | Plain <script> (defines window.HelpAI) |
| elements.esm.js | ESM | <script type="module"> import (CDN-friendly) |
| elements-web-component.esm.js | ESM | Same, registers <web-ai-chat> on import |
| index.mjs / web-component.mjs | ESM | Bundlers (Vite, webpack, esbuild) — bare imports kept |
| elements.cjs.js | CJS | require() from Node / legacy tooling |
| style.css | CSS | <link rel="stylesheet"> |
| schema.json | JSON Schema | Dashboard config UIs, backend handshake validation, 3rd-party tooling |
| schema.mjs | ESM | Zod runtime schemas: import { widgetConfigSchema } from "@helpai/elements/schema" |
Every bundle exposes the same surface (mount, init, hook, types).
Pick whichever matches how your page loads scripts.
Standalone ESM bundle (browser-ready, no build needed)
elements.esm.js is a fully self-contained ESM bundle — every
dependency (preact, signals, streaming-markdown) inlined. Drop into
any page with <script type="module">. No bundler, no import map.
<script type="module">
import { mount } from "https://cdn.jsdelivr.net/npm/@helpai/elements@latest/elements.esm.js";
mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: document.querySelector("#chat"),
});
</script>Web-component variant (self-registers <web-ai-chat> on import):
<script type="module">
import "https://cdn.jsdelivr.net/npm/@helpai/elements@latest/elements-web-component.esm.js";
</script>
<web-ai-chat
public-key="agent_pk_..."
ai-agent-deployment-id="..."
></web-ai-chat>The brand CDN serves the same files:
https://cdn.help.ai/elements/latest/elements.js— IIFE (one-line<script>, notype="module")https://help.ai/elements.esm.js— standalone ESMhttps://help.ai/elements-web-component.esm.js— web-component ESM
Production tip. Pin a specific version (
@1.4.0, not@latest) so a published patch can't surprise you. jsDelivr caches per-version aggressively; pinned URLs are immutable and CDN-friendly.
+esmvselements.esm.js. jsDelivr's/+esmflag tries to auto-bundle on demand but trips on bare-specifier resolution for some packages.elements.esm.jsis pre-bundled at release time — always works, always immutable.
Framework integrations
React / Next.js / Preact
// app/_components/Chat.tsx
import { useEffect, useRef } from "react";
import type { ChatWidgetInstance } from "@helpai/elements";
export function Chat() {
const containerRef = useRef<HTMLDivElement>(null);
const instanceRef = useRef<ChatWidgetInstance | null>(null);
useEffect(() => {
let alive = true;
import("@helpai/elements").then(({ mount }) => {
if (!alive || !containerRef.current) return;
instanceRef.current = mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: containerRef.current,
});
});
return () => {
alive = false;
instanceRef.current?.destroy();
};
}, []);
return <div ref={containerRef} style={{ height: 600 }} />;
}Or just register the web component once and use it as JSX (React 19+ treats unknown tags as web components automatically):
import "@helpai/elements/web-component";
export function Chat() {
return <web-ai-chat public-key="agent_pk_..." ai-agent-deployment-id="..." mode="inline" />;
}Vue 3
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import type { ChatWidgetInstance } from "@helpai/elements";
const containerRef = ref<HTMLDivElement | null>(null);
let instance: ChatWidgetInstance | null = null;
onMounted(async () => {
const { mount } = await import("@helpai/elements");
if (containerRef.value) {
instance = mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: containerRef.value,
});
}
});
onUnmounted(() => instance?.destroy());
</script>
<template>
<div ref="containerRef" style="height: 600px" />
</template>Vue treats <web-ai-chat> as a custom element automatically — no
config needed for unknown tags. To silence the dev warning, mark it
explicitly in vite.config.ts:
export default defineConfig({
plugins: [vue({ template: { compilerOptions: { isCustomElement: (t) => t.startsWith("web-ai-") } } })],
});Angular
// app.config.ts — allow custom elements
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
export class AppModule {}// chat.component.ts
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from "@angular/core";
@Component({
selector: "app-chat",
template: `<div #host style="height: 600px"></div>`,
})
export class ChatComponent implements AfterViewInit, OnDestroy {
@ViewChild("host", { static: true }) host!: ElementRef<HTMLDivElement>;
private instance: { destroy(): void } | null = null;
async ngAfterViewInit() {
const { mount } = await import("@helpai/elements");
this.instance = mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: this.host.nativeElement,
});
}
ngOnDestroy() {
this.instance?.destroy();
}
}Svelte / SvelteKit
<script lang="ts">
import { onMount } from "svelte";
import type { ChatWidgetInstance } from "@helpai/elements";
let host: HTMLDivElement;
let instance: ChatWidgetInstance | null = null;
onMount(async () => {
const { mount } = await import("@helpai/elements");
instance = mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: host,
});
return () => instance?.destroy();
});
</script>
<div bind:this={host} style="height: 600px" />Vanilla / no-framework
<script type="module">
import { mount } from "https://cdn.jsdelivr.net/npm/@helpai/elements@latest/elements.esm.js";
mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "inline" },
target: document.querySelector("#chat"),
});
</script>
<div id="chat" style="height: 600px"></div>Element variations
| Variation | UX |
| ------------ | -------------------------------------------------------------------------------------- |
| floating | Floating launcher FAB + popover panel (default) |
| inline | Full chat block in page flow, sized to its container |
| modal | Centered modal window with dimmed backdrop. Page brings its own trigger button |
| drawer | Edge-attached, non-modal panel; the page remains interactive |
| page | Full viewport with sidebar (logo + nav + conversation list) |
| standalone | Full viewport, panel only (no sidebar) |
Plus an orthogonal presentation.iframe: true flag that wraps any of the above in
a same-origin iframe for strict JS + CSS isolation.
Pick at mount time via presentation: { mode: "<value>" } or the mode="<value>"
attribute. See https://help.ai/docs/elements/modes.
Configuration
The element reads its per-deployment widget configuration from your
Help AI workspace at handshake time — colors, launcher
chrome, strings, action layout, and feature visibility flow through
HandshakeResponse.config. Welcome and page content use sibling
handshake fields; model and tool selection stay server-owned. You don't
recompile per customer.
A handful of options live in the install snippet itself:
mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
presentation: { mode: "floating" },
baseUrl: "https://help.ai", // omit to use the brand default
userContext: { id: "u_123", email: "[email protected]" },
theme: "dark", // "auto" | "light" | "dark" | overrides object
i18n: { defaultLocale: "en" },
debug: "info", // optional — opens the structured log firehose
});Full option reference: https://help.ai/docs/elements/configuration.
Lifecycle hooks
import { hook } from "@helpai/elements";
hook("*", "open", (inst) => analytics.track("agent_opened", { id: inst.widgetId }));
hook("*", "message", (inst, _event, msg) => console.log(msg.role, msg.text));The global object exposes the same API for non-bundled usage:
HelpAI.hook("*", "*", (inst, event, data) => {
/* … */
});Full event map: https://help.ai/docs/elements/events.
Theming
Pass theme overrides at mount:
mount({
publicKey: "agent_pk_...",
aiAgentDeploymentId: "...",
theme: {
accent: "#10B981",
accentText: "#ffffff",
radius: "10px",
fontFamily: "Inter, system-ui, sans-serif",
},
});Or import the standalone stylesheet and style the host element yourself:
@import "@helpai/elements/style.css";Full theming reference: https://help.ai/docs/elements/theming.
More framework recipes
WordPress, Webflow, Shopify, vanilla CMS, code playgrounds, MDX — https://help.ai/docs/elements/frameworks.
Browser support
Modern evergreens: Chrome / Edge ≥ 109, Firefox ≥ 110, Safari ≥ 16. iOS ≥ 16. No IE / Legacy Edge.
Links
- Docs: https://help.ai/docs/elements
- Site: https://help.ai
- CDN: https://cdn.help.ai/elements/latest/elements.js
License
MIT
