There is no @appmint/chat package on npm — chat-client/package.json is private: true with no exports. The only delivery path is the CDN-hosted UMD bundle. For React apps, write a tiny client wrapper that injects the script and calls window.AppmintChat.init(...).
The bundle lives at https://web.appmint.space/chat-client/appmint-chat.js. Once loaded it exposes a global window.AppmintChat with a single init(config) method. A React wrapper is just a useEffect that injects the <script> tag, then calls init once it loads.
The wrapper component
The yugo reference implementation (/Users/imzee/projects/yugo/src/components/AppmintChat.tsx) is the canonical pattern. Copy it as-is, or adapt to your styling conventions.
'use client';
import { useEffect } from 'react';
type AppmintChatProps = {
orgId?: string;
configId?: string;
appId?: string;
className?: string;
style?: React.CSSProperties;
theme?: string;
language?: string;
containerId?: string;
defaultPath?: string;
};
const AppmintChatComponent = ({
orgId,
configId,
appId,
className = '',
style = {},
theme = 'light',
language = 'en',
containerId = 'appmint-chat-container',
defaultPath = '',
}: AppmintChatProps) => {
useEffect(() => {
const initializeChat = () => {
if ((window as any).AppmintChat) {
(window as any).AppmintChat.init({
containerId,
orgId,
configId,
appId,
className,
style,
defaultPath,
theme,
language,
});
}
};
const existingScript = document.getElementById('appmint-chat-script');
if (!existingScript) {
const script = document.createElement('script');
script.id = 'appmint-chat-script';
script.src = 'https://web.appmint.space/chat-client/appmint-chat.js';
script.async = true;
script.onload = initializeChat;
document.body.appendChild(script);
} else {
initializeChat();
}
}, [orgId, configId, appId, theme, language, containerId]);
return <div id={containerId} className="w-full h-full" />;
};
export default function AppmintChat(props: AppmintChatProps) {
if (!props.configId || !props.appId) return null;
return <AppmintChatComponent {...props} />;
}
Mount it once near the root
Render the wrapper once near the root of your tree. It mounts a div, injects the script, and calls init. The widget positions itself fixed to the viewport.
export function AppShell({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<AppmintChat
orgId="your-org-id"
configId="67169ccce05fcd6eb50e6dff"
appId="chat-client"
theme="light"
/>
</>
);
}
Required props are orgId, configId, and appId. Everything else is optional. The full prop list is in Configuration.
With a known visitor
Identity is plumbed through the init config — pass it through from your wrapper:
<AppmintChat
orgId="your-org-id"
configId="67169ccce05fcd6eb50e6dff"
appId="storefront"
/* You'll need to extend the wrapper above to forward user / token */
/>
The yugo reference wrapper does not currently forward user and token — extend the prop list and the init call if you need authenticated visitors. The bundle accepts user: { email, firstName, lastName } and token (a chat-scoped JWT minted server-side).
The token is a JWT issued by AppEngine, not your app's session token. Mint one server-side via the customer signin flow described in Authentication.
Vite, Next.js Pages Router, CRA
The wrapper above is a 'use client' component — it relies on window, document, and runs the script-tag injection on mount. It works in any React tree that runs in the browser. For Next.js App Router, see the Next.js integration page for the SSR-safe pattern.
Multiple widgets on the same page
Don't. The bundle's chat store is a singleton — two wrappers on one page would share state. If you need separate surfaces (e.g. a sales chat and a support chat), pick one config and let the agent route inside AppEngine.
Styles
The bundle inlines its CSS, so you don't need a separate stylesheet import. If you're seeing unstyled markup, the script tag may not have loaded — check DevTools → Network for appmint-chat.js.
The widget uses Tailwind classes scoped under its own root. If your host app also uses Tailwind, the two trees coexist — but if you're using Tailwind v3's preflight in a way that touches body styles, the floating positions may shift. Anchor the widget inside a wrapper with position: relative if you see drift.
Next steps
- Configuration — every prop, with types.
- Events and hooks — listen for messages from your own code.
- Theming — match your brand.