Framework Guides
The Widget SDK uses standard Web Components that work in any modern framework. Import the package once and use the custom element tags directly in your templates. Below are guides for the most popular frameworks - Svelte, Solid, Qwik, and other frameworks that support custom elements work the same way.
React
React 19+ renders custom elements natively. JSX type definitions are included with the SDK so you get full autocompletion and type-checking out of the box. Simply import the package at your app's entry point (or in the component that uses the widget) and use the tag directly.
import '@returningai/widget-sdk'
export function ChannelEmbed({ email, token }: { email: string; token: string }) {
return (
<rai-channel-widget
community-id="YOUR_COMMUNITY_ID"
theme="dark"
data-email={email}
embed-token={token}
bundle-url="https://prod-widgets.returning.ai/channel-widget/bundle/widget.js"
api-url="https://prod-widgets.returning.ai"
v2-api-url="https://api-v2.returning.ai"
domain-key="PROD"
/>
)
}Vue
Vue treats unknown tags as custom elements automatically when they contain a hyphen. Import the SDK in your component's <script setup> block and bind attributes with the standard : prefix.
<script setup>
import '@returningai/widget-sdk'
const props = defineProps<{ token: string }>()
</script>
<template>
<rai-channel-widget
community-id="YOUR_COMMUNITY_ID"
theme="dark"
:data-email="user.email"
:embed-token="props.token"
bundle-url="https://prod-widgets.returning.ai/channel-widget/bundle/widget.js"
api-url="https://prod-widgets.returning.ai"
v2-api-url="https://api-v2.returning.ai"
domain-key="PROD"
/>
</template>Angular
Angular requires you to opt into custom elements by adding CUSTOM_ELEMENTS_SCHEMA to your module (or standalone component) configuration. Import the SDK in your module file so the elements are registered before Angular bootstraps the template.
import '@returningai/widget-sdk'
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })Then use the widget tag in your template. Use [attr.data-email] for dynamic attribute binding:
<rai-channel-widget
community-id="YOUR_COMMUNITY_ID"
theme="dark"
[attr.data-email]="user.email"
[attr.embed-token]="token"
bundle-url="https://prod-widgets.returning.ai/channel-widget/bundle/widget.js"
api-url="https://prod-widgets.returning.ai"
v2-api-url="https://api-v2.returning.ai"
domain-key="PROD"
></rai-channel-widget>Qwik
Qwik handles custom elements natively - no special configuration needed. The key detail is that the SDK import must run on the client, not during Qwik's SSR pass. Use useVisibleTask$ with { strategy: 'document-ready' } to load the SDK eagerly after the document load event. The widget tag itself can be in the server-rendered output.
import { component$, useVisibleTask$ } from '@builder.io/qwik'
export const ChannelEmbed = component$<{ token: string }>((props) => {
useVisibleTask$(() => {
import('@returningai/widget-sdk')
}, { strategy: 'document-ready' })
return (
<rai-channel-widget
community-id="YOUR_COMMUNITY_ID"
theme="dark"
embed-token={props.token}
bundle-url="https://prod-widgets.returning.ai/channel-widget/bundle/widget.js"
api-url="https://prod-widgets.returning.ai"
v2-api-url="https://api-v2.returning.ai"
domain-key="PROD"
/>
)
})Qwik's resumability model means the widget tag is already in the DOM when the SDK loads - no hydration mismatch. The embed-token should be passed from your server-side route loader so it's baked into the initial HTML.