@pixygon/chatbot-react
v0.3.0
Published
React + MUI pages for the Pixygon chatbot: knowledge base admin, chat, analytics, embeddable widget.
Readme
@pixygon/chatbot-react
Ready-to-mount React 18/19 + MUI 6/7 + RTK Query pages for the Pixygon
chatbot stack. Pair with @pixygon/chatbot-server
on the API side.
+----------------------+ +----------------------+
| Host React app |----->| createChatbotComponents()
| (your baseApi here) | +----------------------+
+----------------------+ |
v
KnowledgePage · ChatPage · ChatAnalyticsPage · EmbedChatPage · ChatbotSettings
|
v
HTTP -> chatbot-serverYou configure once at boot, then mount the components in your router or settings tree. Hooks close over the active tenant id, branding, and your existing RTK Query base.
Install
npm install @pixygon/chatbot-reactPeer dependencies the host already has:
| Peer | Range |
|---|---|
| react / react-dom | ^18 or ^19 |
| @mui/material / @mui/icons-material | ^6 or ^7 |
| @emotion/react / @emotion/styled | ^11 |
| @reduxjs/toolkit | ^2 |
| react-redux | ^9 |
The host's baseApi should include these RTK Query tag types so cache
invalidation works:
tagTypes: [..., "Knowledge", "ChatConversation"]Configure once
// src/chatbot.tsx
import { createChatbotComponents } from "@pixygon/chatbot-react";
import { useParams } from "react-router";
import { baseApi } from "@/apis/baseApi";
import { useAppSelector } from "@/store/store";
import { useGetTenantQuery, useUpdateTenantMutation } from "@/apis/tenantApi";
const chatbot = createChatbotComponents({
apiSlice: baseApi,
pathPrefix: "/tenants", // or "/companies"
useTenantId: () => useAppSelector((s) => s.global.activeTenantId),
apiBase: import.meta.env.VITE_API_URL, // public surface origin
brand: {
name: "TotalHMS",
tagline: "Powered by TotalHMS",
primaryColor: "#8FB7C9",
},
});
export const KnowledgePage = chatbot.KnowledgePage;
export const ChatPage = chatbot.ChatPage;
export const ChatAnalyticsPage = chatbot.ChatAnalyticsPage;
// Small wrapper so the route can hand the slug from useParams down to the page.
export function EmbedChatPageRoute() {
const { tenantSlug } = useParams();
return <chatbot.EmbedChatPage tenantSlug={tenantSlug} />;
}
// Settings card — host supplies tenant + save handler (Tenant model lives here).
export function ChatbotSettings({ tenantId }: { tenantId: string }) {
const { data: tenant } = useGetTenantQuery(tenantId);
const [updateTenant] = useUpdateTenantMutation();
return (
<chatbot.ChatbotSettings
tenant={tenant ?? null}
onSave={(patch) =>
updateTenant({ tenantId, patch }).unwrap().then(() => undefined)
}
/>
);
}Drop into routes
import { KnowledgePage, ChatPage, ChatAnalyticsPage, EmbedChatPageRoute } from "@/chatbot";
<Route path="/embed/chat/:tenantSlug" element={<EmbedChatPageRoute />} />
<Route element={<DashboardLayout />}>
<Route path="/knowledge" element={<KnowledgePage />} />
<Route path="/chat" element={<ChatPage />} />
<Route path="/chat-analytics" element={<ChatAnalyticsPage />} />
</Route>Drop into a settings page
<ChatbotSettings tenantId={activeTenantId} />What you get
| Component | Purpose |
|---|---|
| KnowledgePage | List, paste/upload, delete knowledge documents per tenant |
| ChatPage | Operator chat UI with session-keyed threads and citations |
| ChatAnalyticsPage | KPI tiles · knowledge gaps · top questions · keywords · semantic clusters · cost timeseries · source usage · question drill-down |
| EmbedChatPage | Iframe-friendly anonymous chat for the public surface |
| ChatbotSettings | Per-tenant monthly cost cap + copy-pasteable embed snippet |
| ChatLauncher | Floating bottom-right launcher (fixed FAB) that expands into a compact chat panel. Drop one into your DashboardLayout and it's always one click away. |
Floating launcher
import { ChatLauncher } from "@/chatbot";
export default function DashboardLayout() {
return (
<Box sx={{ display: "flex", minHeight: "100vh" }}>
{/* … your nav, app bar, outlet … */}
<ChatLauncher />
</Box>
);
}The launcher closes over useTenantId + brand color from your
createChatbotComponents config, so it has no props. It self-positions at
bottom: 24, right: 24 with z-index: 1300 to float above MUI dialogs.
Full-screen on mobile, fixed 380×580 on desktop.
Embed widget
chatbot.js is shipped as a static file inside the package. Drop it in your
app's public/ so it's served at /chatbot.js:
cp node_modules/@pixygon/chatbot-react/public/chatbot.js public/chatbot.jsThen anyone can embed your chatbot on any HTML page:
<script src="https://app.example.com/chatbot.js"
data-tenant-slug="acme"
defer></script>The widget renders a floating launcher, opens an iframe pointed at
/embed/chat/<slug> on your dashboard, and postMessages a
pixygon-chatbot:close event when the user closes it. The ChatbotSettings
card auto-generates the snippet with the right URL.
Hooks-only API
Skip the pages if you want to build your own UI:
import { injectChatbotEndpoints } from "@pixygon/chatbot-react";
const {
useListDocumentsQuery,
useCreateDocumentMutation,
useDeleteDocumentMutation,
useSendMessageMutation,
useGetConversationQuery,
useRateMessageMutation,
useChatOverviewQuery,
useKnowledgeGapsQuery,
useSemanticClustersQuery,
// ...
} = injectChatbotEndpoints(baseApi, { pathPrefix: "/tenants" });Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| apiSlice type error | The host's baseApi doesn't match the loose Api<any,…> type | Use ^0.1.2 or later — the type was widened to accept any host base |
| Chat send returns 500 with PIXYGON_AI_UNCONFIGURED | PIXYGON_API_KEY not set on the API host | Add it in the host's env / Coolify |
| Hooks return undefined reducer errors | The host's RTK Query store isn't including the chatbot's injected endpoints | Make sure apiSlice you pass is the same instance you mount in configureStore({ middleware }) |
| Embed widget never opens | chatbot.js wasn't copied to your public/ | cp node_modules/@pixygon/chatbot-react/public/chatbot.js public/chatbot.js |
| MUI v7 type errors | This package's peer range covers v6 and v7 since ^0.1.1 | Use ^0.1.4 or later — both MUI generations are supported |
Versioning notes
0.1.0— initial scaffold (file-dep era, requires host workaround for RTK types)0.1.2— RTK Query types loosened so concrete host APIs assign cleanly0.1.3— README + MUI v7 peer accepted0.1.4— addedChatLauncherfloating widget
No breaking changes in the 0.1.x line — bumping is safe within minor.
Companion package
@pixygon/chatbot-server (≥0.3.0) is the Express + Mongoose backend these
components talk to. All AI calls flow through PixygonServer's gateway —
no direct-to-provider bypass — so per-API-key margin reporting on
admin.pixygon.io stays accurate. See its README for the API wire-up.
License
MIT.
