Getting Started
In this example, we are going to walk through setting up reachat in your project and creating your first chatbot. This guide assumes you’ve already followed the steps in Setup to install the package.
By now, you should have the basic building blocks for the chat component with minimal styling, and no functionality. Let’s add some basic functionality to the chat component. For now, we’ll just use state variables to simulate creating and deleting sessions as well as starting conversations.
Creating a new session
We’ll start by adding the ability to create a new session by adding a onNewSession handler:
const [sessions, setSessions] = useState<Session[]>([]);
const handleNewSession = () => {
const newId = (sessions.length + 1).toString();
setSessions([
...sessions,
{
id: newId,
title: `New Session #${newId}`,
createdAt: new Date(),
updatedAt: new Date(),
conversations: [],
},
]);
};
return (
<Chat sessions={sessions} onNewSession={handleNewSession}>
<SessionsList>
<NewSessionButton />
<SessionGroups />
</SessionsList>
<SessionMessagePanel>
<SessionMessagesHeader />
<SessionMessages />
<ChatInput />
</SessionMessagePanel>
</Chat>
);Selecting a session
Now we want to be able to select the new session that we created. Again, we’ll handle
this with a state variable - activeSessionId.
const [activeSessionId, setActiveSessionId] = useState<string>();
...
return (
<Chat
sessions={sessions}
activeSessionId={activeSessionId}
onNewSession={handleNewSession}
onSelectSession={setActiveSessionId}
>
<SessionsList>
<NewSessionButton />
<SessionGroups />
</SessionsList>
<SessionMessagePanel>
<SessionMessagesHeader />
<SessionMessages />
<ChatInput />
</SessionMessagePanel>
</Chat>
);Deleting a session
Let’s handle deleting the session that we created by passing an onDeleteSession prop
to the Chat component. We’ll also check to see if we need to reset the activeSessionId
if the session we are deleting is the one that is currently active.
const handleDeleteSession = (id: string) => {
setSessions(sessions.filter((session) => session.id !== id));
if (id === activeSessionId) {
setActiveSessionId(undefined);
}
};
...
return (
<Chat
sessions={sessions}
activeSessionId={activeSessionId}
onNewSession={handleNewSession}
onSelectSession={setActiveSessionId}
onDeleteSession={handleDeleteSession}
>
<SessionsList>
<NewSessionButton />
<SessionGroups />
</SessionsList>
<SessionMessagePanel>
<SessionMessagesHeader />
<SessionMessages />
<ChatInput />
</SessionMessagePanel>
</Chat>
);Handling session conversations
Now that we can create, select, and delete sessions, let’s add the ability to start a new
conversation. We’ll need to add an onSendMessage handler here to handle adding conversations
to the active session. We’ll just use a simple example response for now, but in a real
application, you would likely be making a request to a backend service here.
Note: you can also optionally add an onStopMessage handler to handle
stopping a message that is currently being sent.
We can also handle loading state here and pass isLoading prop to the component.
const [loading, setLoading] = useState<boolean>(false);
const handleNewMessage = (message: string) => {
setLoading(true);
const current = sessions.find((s) => s.id === activeSessionId);
if (current) {
const newMessage: Conversation = {
id: `${current.id}-${current.conversations.length}`,
question: message,
response: "this is an example response",
createdAt: new Date(),
updatedAt: new Date(),
};
const updated = {
...current,
conversations: [...current.conversations, newMessage],
};
setSessions([
...sessions.filter((s) => s.id !== activeSessionId),
updated,
]);
}
setLoading(false);
};
...
return (
<Chat
sessions={sessions}
activeSessionId={activeSessionId}
onNewSession={handleNewSession}
onSelectSession={setActiveSessionId}
onDeleteSession={handleDeleteSession}
onSendMessage={handleNewMessage}
isLoading={loading}
>
<SessionsList>
<NewSessionButton />
<SessionGroups />
</SessionsList>
<SessionMessagePanel>
<SessionMessagesHeader />
<SessionMessages />
<ChatInput />
</SessionMessagePanel>
</Chat>
);
Styling
Besides functionality, of course, styling would be one of the first things that
comes to mind. There is a default theme that you can customize with basic colors by
defining design tokens in your CSS with Tailwind v4’s @theme directive.
For example, if we wanted to change the default blue to a purple, we could override the primary color tokens like this:
@theme {
--color-primary: #a855f7; /* purple-500 */
--color-primary-hover: #9333ea; /* purple-600 */
--color-secondary: #d8b4fe; /* purple-300 */
}To customize chat specific styles, add a theme.ts file which extends the chatTheme
object.
import { chatTheme as defaultTheme, ChatTheme } from "reachat";
import { twMerge } from "tailwind-merge";
export const chatTheme: ChatTheme = {
...defaultTheme,
sessions: {
...defaultTheme.sessions,
console: twMerge(defaultTheme.sessions.console, "min-w-[300px]"),
session: {
...defaultTheme.sessions.session,
delete:
"[&>svg]:w-4 [&>svg]:h-4 opacity-70 hover:opacity-100 transition-opacity",
},
},
messages: {
...defaultTheme.messages,
base: "py-4 pr-4",
message: {
...defaultTheme.messages.message,
question: twMerge(
defaultTheme.messages.message.question,
"text-purple-300 text-lg",
),
response: "border-l border-purple-300 pl-4",
},
},
};Then pass the exported chatTheme to your <Chat /> component.
<Chat
sessions={sessions}
activeSessionId={activeSessionId}
onNewSession={handleNewSession}
onSelectSession={setActiveSessionId}
onDeleteSession={handleDeleteSession}
onSendMessage={handleNewMessage}
isLoading={loading}
theme={chatTheme}
>
<SessionsList>
<NewSessionButton />
<SessionGroups />
</SessionsList>
<SessionMessagePanel>
<SessionMessagesHeader />
<SessionMessages />
<ChatInput />
</SessionMessagePanel>
</Chat>…and that’s it!
That’s the basics of getting things off the ground. But there’s plenty more you can do with the Reachat building blocks. It handles the hard bits for you:
- Markdown display with custom remark plugins
- Multi-file uploads with type-aware renderers (images, CSV, PDF, etc.)
- Source citations
- Auto-scroll and scroll-to-bottom interactions
@mentions and/slash commands- LLM-driven UI via the Component Catalog
- Mobile/companion mode
so you can focus on building out a chat experience tailored to your users.
Example repo
We’ve created a example repo that demonstrates the previous example that you can clone and run locally to get you started.
Advanced options
Most components in the chat tree are slot-based — you can swap them out for your own React components without giving up the rest of reachat’s behavior. See the Custom Components guide and the matching storybook demo for examples.