@webotme/react-native
v0.1.1
Published
Drop-in AI chatbot for React Native and Expo apps. Same bot, training and AutoFlow as the WebotMe web widget.
Maintainers
Readme
@webotme/react-native
Drop-in AI chatbot for React Native and Expo. Same bot, same training and same AutoFlow as the WebotMe web widget.
Install
npm install @webotme/react-native react-native-webviewreact-native-webview is a peer dependency — Expo apps can get it with
npx expo install react-native-webview.
Requires a development build, not Expo Go, because
react-native-webviewis a native module.
Use
Wrap your app once, then show the widget anywhere.
import { WebotMeProvider, WebotMeLauncher } from "@webotme/react-native";
export default function App() {
return (
<WebotMeProvider
botId="YOUR_BOT_ID"
apiBaseUrl="https://your-api.com"
chatBaseUrl="https://your-frontend.com"
>
<RootNavigator />
</WebotMeProvider>
);
}Floating bubble (handles open/close automatically):
import { WebotMeLauncher } from "@webotme/react-native";
<WebotMeLauncher position="bottom-left" icon="💬" />Inline chat (renders in place, no launcher needed):
import { WebotMeWidget } from "@webotme/react-native";
<WebotMeWidget mode="inline" />Controlled modal (if you want your own trigger):
import { WebotMeWidget } from "@webotme/react-native";
import { useState } from "react";
function ChatButton() {
const [open, setOpen] = useState(false);
return (
<>
<Pressable onPress={() => setOpen(true)}>
<Text>Open Chat</Text>
</Pressable>
<WebotMeWidget visible={open} onClose={() => setOpen(false)} />
</>
);
}Config
| Prop | Required | Description |
| --- | --- | --- |
| botId | yes | Bot ID from the WebotMe dashboard |
| apiBaseUrl | yes | Backend base URL. Never localhost on a device |
| chatBaseUrl | no | Frontend that serves /chat/{botId}. Falls back to apiBaseUrl |
| userId | no | Stable visitor id. Generated if omitted |
| theme | no | primary, background, surface, text, muted |
| welcome | no | Message shown before the bot replies |
| screenContext | no | Sent with every message so AutoFlow knows the screen |
| timeoutMs | no | Default 30000 |
| resetKey | no | Change it to start a new session |
Widget Props
| Prop | Required | Description |
| --- | --- | --- |
| mode | no | "modal" (default) opens full-screen; "inline" renders in place |
| variant | no | "web" (default) loads the Vercel chat page; "native" uses a native RN chat UI |
| visible | no | Modal only — open when true (default false) |
| onClose | no | Called when modal closes (modal only) |
| title | no | Modal header title (modal/native) |
| theme | no | Override primary, background, surface, text, muted |
| showClose | no | Show header close button (modal/native, default true) |
AutoFlow
Web AutoFlow reads the page DOM. Native apps have no DOM, so send a
screenContext snapshot and the same engine guides your app.
<WebotMeProvider
botId="YOUR_BOT_ID"
apiBaseUrl="https://your-api.com"
screenContext={{
name: "pricing",
title: "Plans",
visibleText: ["Free", "Pro"],
buttons: [{ id: "buy_pro", text: "Buy Pro" }],
links: [{ id: "faq", text: "FAQ", route: "/faq" }],
}}
>The server answers with text plus, when it wants the app to act, an action:
| Action | Shape |
| --- | --- |
| navigate | { type: "navigate", route, label } |
| click | { type: "click", targetId, label } |
| fill | { type: "fill", fieldId, value, label } |
| checkout | { type: "checkout", url, label } |
Native API instead of the web view
If you want your own UI, skip the WebView and use the client directly.
import { useWebotMeChat } from "@webotme/react-native";
const { messages, send, sending, error } = useWebotMeChat();Or bypass React entirely:
import { WebotMeClient } from "@webotme/react-native";
const client = new WebotMeClient({ botId, apiBaseUrl });
await client.discover(); // feature-detect the server
const { text, action } = await client.send({
message: "Hello",
sessionId,
userId,
screenContext,
});Errors
Every failure is a WebotMeError with a stable code:
INVALID_REQUEST, UNAUTHORIZED, FORBIDDEN, BOT_NOT_FOUND,
RATE_LIMITED, PLAN_LIMIT_REACHED, AI_UNAVAILABLE, INTERNAL_ERROR,
NETWORK_ERROR.
try {
await client.send({ message, sessionId, userId });
} catch (err) {
if (err instanceof WebotMeError && err.code === "PLAN_LIMIT_REACHED") {
// show the upgrade screen
}
}Security
Never ship an API key in a mobile app — apps can be decompiled. This package
authenticates with the bot ID only. For server-to-server calls keep the key on
your own backend and use POST /api/sdk/chat.
Endpoints used
| Purpose | Endpoint |
| --- | --- |
| Contract | GET /api/chatbot/public/{botId}/native-chat/v1 |
| Chat | POST /api/chatbot/public/{botId}/native-chat/v1 |
| Bot config | GET /api/chatbot/public/{botId} |
| Sessions | GET /api/chatbot/public/{botId}/sessions/{visitorId} |
| New session | POST /api/chatbot/public/{botId}/session/new |
| Web chat page | GET {chatBaseUrl}/chat/{botId} |
License
UNLICENSED
