Assumptions
- Next.js
14.xor later, App Router (app/directory). - Node 20+ (for
Response.json,fetch). - An LLM API key (OpenAI, Grok, LM Studio, or any other OpenAI-compatible endpoint).
- Optional: a
pbt_…bot token if you want dashboard analytics.
1. Install
react, react-dom) come from your existing
Next.js install.
2. Environment variables
Create.env.local at the project root (never commit this file):
.env.local to .gitignore if it isn’t already.
3. Server-side chat proxy
Createapp/api/probot-chat/route.ts. This route holds the LLM key and is
the only place your web app calls the provider:
Use
export const runtime = "nodejs"; if you’re on Vercel and your LLM
responses might take longer than the edge runtime’s response budget. The
Node runtime has a much longer default timeout.4. Client widget
Createcomponents/BotWidget.tsx:
sendMessage passes the AbortSignal through so a component
unmount (e.g. route change while a reply is in flight) cancels the pending
fetch cleanly.
5. Mount into the root layout
Mount the widget once, inapp/layout.tsx, so every page carries the
floating chat bubble:
npm run dev, visit http://localhost:3000, click the chat
bubble.
Loading the knowledge base from a file
Inlining a multi-KB string bloats the client bundle. Store the knowledge as a JSON or Markdown file and import it:Restricting the proxy to your origin
Next.js API routes accept cross-origin requests by default. If your bot’s knowledge is sensitive, add a same-origin check:Adding per-visitor rate limiting
Every visitor turn = one LLM call = one bill. Rate-limit the proxy per IP:Streaming responses
The stockcreateOpenAIHandler is non-streaming (returns the full reply
after the LLM finishes). If you want typewriter-style streaming, implement
sendMessage yourself with an incremental TransformStream:
<ProbotBot /> for the headless
useProbotChat hook and drive tokens in yourself. See the
React example for the hook API.
Testing locally
{ "reply": … }, the widget will work. If it returns
{ "error": … }, fix the proxy first - the widget won’t magically make
a broken server route work.
Deploying
Vercel:- Set env vars in the Vercel dashboard:
OPENAI_API_KEY(encrypted) andNEXT_PUBLIC_PROBOT_TOKEN(public). - Push to your production branch.
- Set the same env vars in your platform’s secrets store.
- Ensure the process running Next.js has network egress to the LLM
provider (
api.openai.com,api.x.ai, etc.). - Confirm
/api/probot-chatresponds under production DNS before flipping traffic.
Full example repo
The above files map to a working Next.js 14 project. If you want a scaffolded starter with all this pre-wired, see thepackages/probot-self-hosted
directory in the ProBot monorepo - the package README’s Quick example
covers the same setup in a condensed form.