chatproject
v1.0.7
Published
Embeddable chat widget for React/Next.js — real-time messaging powered by Pubby
Maintainers
Readme
chatproject
Embeddable real-time chat widget for React and Next.js, powered by Pubby.
- Drop-in
<ChatWidget />component or headlessChatProvider+useChatContextfor custom UI - Real-time messaging via WebSocket (Pubby)
- shadcn UI compatible — inherits your CSS variables automatically
- Channels, moderation, bot commands, emoji picker, GIF picker, message history
- React 18+ / React 19, Next.js 13+ / Next.js 16
Install
npm install chatprojectQuick Start
"use client";
import { ChatWidget } from "chatproject";
import "chatproject/styles.css";
export function Chat({ token }: { token: string }) {
return (
<div style={{ width: 400, height: 600 }}>
<ChatWidget
token={token}
apiUrl="https://api.chatproject.io"
onClose={() => console.log("closed")}
/>
</div>
);
}The token is a JWT generated server-side via the /api/auth/generate-widget-token endpoint. See Authentication below.
Authentication
Generate a token from your backend — never expose your API key client-side.
// app/api/chat-token/route.ts (Next.js App Router)
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { userId, name, email } = await request.json();
const res = await fetch(
`${process.env.CHAT_API_URL}/api/auth/generate-widget-token`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": process.env.CHAT_API_KEY!,
},
body: JSON.stringify({ externalUserId: userId, name, email }),
},
);
const data = await res.json();
return NextResponse.json(data);
}Omit externalUserId, name, and email to get a read-only anonymous token.
Props
| Prop | Type | Required | Default | Description |
| ------------- | -------------------------- | -------- | -------------------- | --------------------------------------- |
| token | string | Yes | — | JWT from generate-widget-token |
| apiUrl | string | No | "" (same origin) | Chat API base URL |
| pubbyKey | string | No | — | Pubby app key (usually set via env var) |
| pubbyWsHost | string | No | wss://ws.pubby.dev | Pubby WebSocket endpoint |
| tenorApiKey | string | No | — | Tenor API key for GIF picker |
| onClose | () => void | No | — | Close button callback |
| className | string | No | — | Additional CSS classes |
| theme | Partial<ChatThemeConfig> | No | — | Theme overrides (skips API fetch) |
Custom UI with ChatProvider
Use ChatProvider and useChatContext for full control over the UI:
"use client";
import { ChatProvider, useChatContext } from "chatproject";
import "chatproject/styles.css";
function CustomChat() {
const { messages, sendMessage, connectionState, isReadOnly } =
useChatContext();
return (
<div>
<p>Status: {connectionState}</p>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.sender}</strong>: {msg.message}
</div>
))}
{!isReadOnly && (
<button onClick={() => sendMessage("Hello!")}>Send</button>
)}
</div>
);
}
export function ChatPage({ token }: { token: string }) {
return (
<ChatProvider token={token} apiUrl="https://api.chatproject.io">
<CustomChat />
</ChatProvider>
);
}Context Value
useChatContext() provides:
- Auth:
token,userId,selfName,organizationId,isReadOnly,isAuthenticated - Connection:
connectionState(disconnected|connecting|connected|failed) - Channels:
channels,currentChannelId,setCurrentChannelId,getChannelDisplayName,isLoadingChannels - Messages:
messages,sendMessage,loadMoreMessages,isFetchingHistory,hasMoreHistory - Presence:
channelUserCounts - Moderation:
mutedUsers,muteUser,isChatDisabled - Bots:
botCommands,isBotCommandsLoading - Theme:
themeConfig,isLoadingTheme
Theming
The widget uses shadcn-compatible CSS variables. If your app uses shadcn UI, it inherits your theme with zero configuration.
Without shadcn, set these CSS variables on a parent element or :root:
:root {
--background: 220 20% 10%;
--foreground: 0 0% 95%;
--primary: 210 100% 50%;
--primary-foreground: 0 0% 100%;
--muted: 220 15% 20%;
--muted-foreground: 220 10% 60%;
--border: 220 15% 25%;
--input: 220 15% 25%;
--card: 220 20% 12%;
--accent: 220 15% 20%;
--accent-foreground: 0 0% 95%;
--radius: 0.75rem;
}Exports
// Components
import { ChatWidget } from "chatproject";
import { ChatProvider, useChatContext } from "chatproject";
// Types
import type {
ChatWidgetProps,
ChatMessage,
Channel,
ConnectionState,
ChatThemeConfig,
BotCommandGroup,
BotCommandEntry,
ChatContextValue,
} from "chatproject";
// Styles
import "chatproject/styles.css";License
MIT
