Skip to main content
@asgard-js/react React SDK reference

React SDK (@asgard-js/react)

@asgard-js/react builds on @asgard-js/core to provide a ready-made React chat UI and hooks, so a React application can integrate Asgard chat quickly.

Read the full guide first

Choosing an integration pattern, advanced configuration and common problems are covered in the frontend SDK guide, and every capability has a runnable example at SDK Demo.

Installation​

@asgard-js/react takes @asgard-js/core as a peer dependency, so install both:

npm install @asgard-js/react @asgard-js/core

Importing the stylesheet​

import "@asgard-js/react/style";

This line is needed once. Without it the chatbot renders unstyled.

The <Chatbot> component​

import { Chatbot } from "@asgard-js/react";
import "@asgard-js/react/style";

export default function App() {
return (
<div style={{ height: "100vh" }}>
<Chatbot
title="My AI assistant"
customChannelId="user-123"
config={{
botProviderEndpoint:
"https://api.asgard-ai.com/ns/{namespace}/bot-provider/{botProviderId}",
}}
/>
</div>
);
}

Required props​

PropTypeDescription
config.botProviderEndpointstringThe Bot Provider's endpoint URL
customChannelIdstringThe conversation channel's id, usually a user id or session id

The full prop list is in the Props Reference.

SSR frameworks (Next.js)​

@asgard-js/react depends on browser APIs (window, SpeechRecognition, ResizeObserver), so it cannot run on the server.

Next.js App Router​

"use client";

import dynamic from "next/dynamic";
import "@asgard-js/react/style";

const Chatbot = dynamic(
() => import("@asgard-js/react").then((m) => m.Chatbot),
{ ssr: false },
);

export default function ChatPage() {
return (
<div style={{ height: "100vh" }}>
<Chatbot
title="My AI assistant"
customChannelId="user-123"
config={{
botProviderEndpoint:
"https://api.asgard-ai.com/ns/{namespace}/bot-provider/{botProviderId}",
}}
/>
</div>
);
}

Next.js Pages Router​

import dynamic from "next/dynamic";

const Chatbot = dynamic(
() => import("@asgard-js/react").then((m) => m.Chatbot),
{ ssr: false },
);

Docusaurus / Gatsby​

import BrowserOnly from "@docusaurus/BrowserOnly";

export default function MyPage() {
return (
<BrowserOnly>
{() => {
const { Chatbot } = require("@asgard-js/react");
require("@asgard-js/react/style");
return (
<Chatbot
title="..."
customChannelId="..."
config={{ botProviderEndpoint: "..." }}
/>
);
}}
</BrowserOnly>
);
}

Custom UI (useAsgardContext)​

Inside custom render props such as renderHeader and renderFooter, useAsgardContext gives you the conversation state:

import { useAsgardContext } from "@asgard-js/react";

function CustomHeader() {
const { resetChannel, isConnecting } = useAsgardContext();
return (
<div>
<span>My Bot</span>
<button onClick={resetChannel} disabled={isConnecting}>
Reset conversation
</button>
</div>
);
}

Contexts and providers​

@asgard-js/react exports four contexts, each with a provider and a hook. <Chatbot> wires them up internally; you only reach for them when assembling your own UI.

ContextProviderHookWhat it provides
AsgardServiceContextAsgardServiceContextProvideruseAsgardContextConversation state and actions (resetChannel, isConnecting)
AsgardThemeContextAsgardThemeContextProvideruseAsgardThemeContextTheme settings, defaulting to defaultAsgardThemeContextValue
AsgardTemplateContextAsgardTemplateContextProvideruseAsgardTemplateContextHow message templates render
AsgardAppInitializationContextAsgardAppInitializationContextProvideruseAsgardAppInitializationContextApplication initialization state

FileDropContextProvider and useFileDropContext handle drag-and-drop files.

ThemeScope applies a theme to one subtree, and DEFAULT_CONTENT_MAX_WIDTH is the content area's default maximum width.

Headless integration​

To build your own interface instead of using <Chatbot>, start from these two hooks:

import { useAsgardServiceClient, useChannel } from '@asgard-js/react';

const client = useAsgardServiceClient({
config: { botProviderEndpoint, apiKey },
keepConnectionOnUnmount: false,
});

const channel = useChannel({ client, customChannelId, initMessages });

useAsgardServiceClient creates and manages the AsgardServiceClient lifecycle, returning AsgardServiceClient | null. keepConnectionOnUnmount decides whether the connection survives the component unmounting.

useChannel takes UseChannelProps (client, customChannelId, initMessages, autoResetChannel, onSseMessage, onAuthError and more) and returns UseChannelReturn.

File explorer and sandbox​

Components and hooks for showing a sandbox filesystem:

ExportPurpose
FileExplorer / FileExplorerPanelThe explorer itself and its panel container
FileExplorerProvider / useFileExplorerThe explorer's context and the hook that reads it
useFileExplorerControllerBuilds the explorer's controller, taking UseFileExplorerControllerOptions
FileViewViewer for a single file
createSandboxFsProvidersWraps AsgardServiceClient's sandboxFs* methods into the provider set the explorer expects
useSandboxLaunch / useLaunchedSandboxesLaunch a sandbox, and read the list of launched ones
sandboxAsSource / sandboxesAsSourcesTurn a sandbox into an explorer source
SourceSetFileExplorerThe SourceSet explorer, paired with AsgardSourceSetClient from @asgard-js/core

EMPTY_SOURCE_VIEW is the empty state used when there is no source.

Other components​

ChatHeader is the conversation title bar, and ChatHeaderAction adds action buttons to it. TaskList and SubagentList render tasks and subagents from @asgard-js/core's derived state.

General React utilities​

These hooks carry no Asgard-specific meaning. They are general-purpose helpers the package uses internally and exports along the way: you can use them, but they are not part of the integration surface. useDebounce, useDeepCompareMemo, useResizeObserver, useVisualViewport, useIsAtBottom, useSyncedSpin, usePromptSuggestion.

t is the i18n translation function and Locale is the locale type.

Sandbox browser panel​

SandboxBrowserPanel renders a Sandbox's browser inside your layout and handles the connection, input forwarding and cursor itself.

useSandboxBrowserController({ open?, activeSandboxName? }) owns its open state and which Sandbox it points at. It returns open, activeSandboxName and requestedBrowser, plus openBrowser(), closeBrowser(), toggle(), selectSandbox(name) and requestBrowser(name, { reveal }). requestBrowser opens the panel as well by default; pass reveal: false to switch target without revealing it.

The returned object is memoised so its identity moves only with the state — the panel's connection effect depends on it, and a fresh object each render would reconnect every time.

toRemoteCoords(video, clientX, clientY) converts a pointer position on the panel into the remote screen's coordinates, and fromRemoteCoords(video, x, y) goes the other way. Both account for the video's letterboxing and return null rather than inventing a coordinate they cannot compute. You only call them directly when building your own pointer overlay or annotations.

Interactive demo​

Every prop and capability (message templates, theming, custom rendering, authentication, tool calls) has a runnable example: sdk-demo.asgard-ai.com

Further reading​