PPM

@pixygon/chatbot-react

React + MUI pages for the Pixygon chatbot: knowledge base admin, chat, analytics, embeddable widget.

Install

# .npmrc
@pixygon:registry=https://ppm.pixygon.io/

npm install @pixygon/chatbot-react@0.4.0

Versions

VersionPublishedIntegrity
0.4.0 latest2026-07-21sha512-QAO9r0Gelart7jG…
0.3.0 2026-06-17sha512-MHfBRaGgF3ueWpR…
0.2.0 2026-06-17sha512-RI0WYa0o9AeTfx0…
0.1.5 2026-06-13sha512-mQonUF40RGJg3op…
0.1.4 2026-06-11sha512-/H21QYChX0NQZ5Z…
0.1.3 2026-06-11sha512-fA2r+E34uRRDs/7…
0.1.2 2026-06-11sha512-8Eeecwl1TTcSlnG…
0.1.1 2026-06-11sha512-h7WO2VIdpD5VoRM…
0.1.0 2026-06-11sha512-alZy8Z/jMDQ4VD7…

@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-server

You 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-react

Peer dependencies the host already has:

PeerRange
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

ComponentPurpose
KnowledgePageList, paste/upload, delete knowledge documents per tenant
ChatPageOperator chat UI with session-keyed threads and citations
ChatAnalyticsPageKPI tiles · knowledge gaps · top questions · keywords · semantic clusters · cost timeseries · source usage · question drill-down
EmbedChatPageIframe-friendly anonymous chat for the public surface
ChatbotSettingsPer-tenant monthly cost cap + copy-pasteable embed snippet
ChatLauncherFloating 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.js

Then 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

SymptomCauseFix
apiSlice type errorThe host's baseApi doesn't match the loose Api<any,…> typeUse ^0.1.2 or later — the type was widened to accept any host base
Chat send returns 500 with PIXYGON_AI_UNCONFIGUREDPIXYGON_API_KEY not set on the API hostAdd it in the host's env / Coolify
Hooks return undefined reducer errorsThe host's RTK Query store isn't including the chatbot's injected endpointsMake sure apiSlice you pass is the same instance you mount in configureStore({ middleware })
Embed widget never openschatbot.js wasn't copied to your public/cp node_modules/@pixygon/chatbot-react/public/chatbot.js public/chatbot.js
MUI v7 type errorsThis package's peer range covers v6 and v7 since ^0.1.1Use ^0.1.4 or later — both MUI generations are supported

Versioning notes

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.

All packages · packument JSON