A production-ready chat application template with authentication, conversation persistence, and full ChatBotKit platform integration — built with Next.js, ChatBotKit SDK, next-auth, and shadcn/ui.
Most chat templates wire up a raw LLM call (e.g. OpenAI directly) and leave everything else — tools, data sources, guardrails, authentication — as an exercise for the developer. This template takes a fundamentally different approach by connecting to ChatBotKit platform agents (bots).
When you select an agent in the dropdown, you get the full set of capabilities configured on the ChatBotKit platform, not just a model and a prompt. This includes:
- Skills (Abilities) — Agents can browse the web, generate images, run code, interact with files, and much more — all configured through the platform without writing additional code in your app.
- Datasets & Knowledge Bases — Attach documents, websites, and structured data directly to your agent. RAG retrieval happens on the platform side, so your app stays lean.
- Third-Party Service Authentication — Agents can authenticate with external services like Google Calendar, Notion, Slack, GitHub, and others via the platform's built-in secret management and OAuth flows. Your frontend never touches those credentials.
- Sitemap & Data Ingestion — Automatically crawl and index entire websites or Notion workspaces to build agent knowledge.
- Guardrails & Moderation — Content moderation, PII filtering, and custom guardrails are handled at the platform level, not in your application code.
- Model Flexibility — Switch between OpenAI, Anthropic, Google, and other providers per-agent on the platform. No code changes needed.
- Contact & Conversation Management — Each authenticated user is tracked as a contact, with full conversation history and message persistence managed through the platform API.
The key insight is that your application is a thin client — the intelligence, configuration, and integrations live on the platform. You can update agent behavior, swap models, add new skills, or connect new data sources without redeploying your app.
- Authentication — Google OAuth via next-auth with JWT sessions
- Protected Routes — Middleware-based route protection for
/chat - Streaming Chat — Real-time AI responses using ChatBotKit streaming with
onStart/onFinishlifecycle hooks - Platform Agents — Select from your ChatBotKit bots via a dropdown (with optional filtering via
CHATBOTKIT_BOT_IDS) - Conversation Persistence — Conversations are saved to the platform and associated with contacts, so users can resume past conversations
- Conversation History — Slide-out sidebar showing previous conversations with auto-generated labels
- Contact Tracking — Authenticated users are automatically mapped to ChatBotKit contacts by email
- Modern UI — Built with shadcn/ui components and Tailwind CSS
- Server Actions — Next.js server actions for secure API communication (API keys never reach the client)
- Next.js 14 — App Router with server actions
- ChatBotKit SDK —
@chatbotkit/reactfor client-side streaming,@chatbotkit/sdkfor server-side API - next-auth — Authentication with Google OAuth provider (extensible to GitHub, email, etc.)
- shadcn/ui — Accessible UI components built on Radix primitives
- Tailwind CSS — Utility-first styling with dark mode support
- Node.js 18+
- A ChatBotKit account with at least one bot configured
- Google OAuth credentials (for authentication)
npx create-cbk-appFollow the prompts and configure environment variables (see below).
# Clone the repository
git clone <repo-url>
cd template-nextjs-chat-auth-js
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Edit .env with your values (see Environment Variables below)
# Start the development server
npm run devOpen http://localhost:3000 to get started.
| Variable | Required | Description |
|---|---|---|
CHATBOTKIT_API_SECRET |
Yes | ChatBotKit API token from chatbotkit.com/tokens |
CHATBOTKIT_BOT_IDS |
No | Comma-separated bot IDs to show (e.g., bot_abc,bot_def). Omit to show all bots. |
NEXTAUTH_SECRET |
Yes | Random secret for JWT signing — generate with openssl rand -base64 32 |
NEXTAUTH_URL |
Yes | Your app URL (e.g., http://localhost:3000) |
GOOGLE_CLIENT_ID |
Yes | Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
Yes | Google OAuth client secret |
Note: The AI model, backstory, skills, datasets, and all other agent configuration is managed per-bot on the ChatBotKit platform. Your app simply references the bot by ID — all capabilities come from the platform.
- Sign up or log in at chatbotkit.com
- Go to chatbotkit.com/tokens
- Create a new API token and copy it to your
.envfile - Create at least one bot at chatbotkit.com — it will appear in the agent dropdown
- Go to Google Cloud Console
- Create a new OAuth 2.0 Client ID
- Set authorized redirect URI to
http://localhost:3000/api/auth/callback/google - Copy the Client ID and Client Secret to your
.envfile
Browser (React) Server Actions ChatBotKit Platform
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ ConversationManager │──→│ complete() │──→│ streamComplete() │
│ (streaming client) │←──│ onStart() │ │ Bot config + skills│
│ │ │ onFinish() │ │ Datasets + RAG │
│ Bot Selector │──→│ listBots() │──→│ Contacts │
│ Conversation Sidebar│──→│ listConvos() │──→│ Conversations │
└──────────────┘ └──────────────┘ └──────────────────┘
- Authentication — User signs in via Google OAuth. The session is JWT-based (24h expiry).
- Contact Resolution — On first chat load, the user's email is used to ensure a contact exists on the ChatBotKit platform via
cbk.contact.ensure(). - Bot Selection — Available bots are fetched from the platform. The user selects one from the dropdown.
- Streaming — Messages are sent via server actions. The
streamCompletefunction streams the response token-by-token back to the browser. - Persistence —
onStartcreates a conversation on the platform;onFinishsaves all messages and generates a label. The conversation is linked to the contact. - History — The sidebar fetches past conversations for the current contact and allows resuming them.
The chat uses a stateless streaming pattern — the full message history is sent with every request (no server-side session). Persistence is handled via lifecycle callbacks:
onStart— Creates a new conversation on the platform (or reuses an existing one) and links it to the contact and bot.onFinish— Saves all messages to the conversation and generates a human-readable label from the first exchange.
This gives you the simplicity of stateless streaming with the durability of platform-managed conversations.
├── actions/
│ └── conversation.jsx # Server actions: complete, listBots, listConversations, etc.
├── app/
│ ├── layout.jsx # Root layout with providers
│ ├── page.jsx # Landing page (redirects to /chat or /auth)
│ ├── auth/signin/page.jsx # Custom sign-in page
│ ├── chat/
│ │ ├── page.jsx # Chat page (server component, session gate)
│ │ └── chat-page.jsx # Chat page (client component, all state)
│ └── api/auth/[...nextauth]/
│ └── route.ts # NextAuth API route
├── components/
│ ├── providers.jsx # Session provider wrapper
│ ├── chat/
│ │ ├── bot-selector.jsx # Agent/bot dropdown selector
│ │ ├── chat-area.jsx # Chat container with ConversationManager
│ │ ├── chat-header.jsx # Header with sidebar toggle and user menu
│ │ ├── chat-input.jsx # Auto-resizing textarea with Enter-to-send
│ │ ├── chat-messages.jsx # Message bubbles with copy-to-clipboard
│ │ └── conversation-sidebar.jsx # Slide-out conversation history panel
│ └── ui/ # shadcn/ui primitives (avatar, button, card, etc.)
├── hooks/
│ └── useAutoRevert.js # Auto-reverting state hook
├── lib/
│ ├── auth-options.js # NextAuth configuration
│ └── utils.js # cn() utility for Tailwind class merging
└── middleware.ts # JWT-based route protection
The template fetches your bots directly from the ChatBotKit platform. To configure agents:
- Go to chatbotkit.com and create bots
- Configure each bot's backstory, model, skills, datasets, and integrations
- The bots will automatically appear in the agent dropdown
- Optionally set
CHATBOTKIT_BOT_IDSin.envto restrict which bots are shown
When a bot is selected, its full platform configuration is used — including all skills, datasets, connected services, and guardrails. You can update any of these on the platform and the changes take effect immediately, without redeploying your app.
To only show specific bots in the dropdown, set CHATBOTKIT_BOT_IDS:
CHATBOTKIT_BOT_IDS=bot_abc123,bot_def456You can also add client-side functions to the functions array in actions/conversation.jsx. These run alongside the platform-configured skills:
{
name: 'lookupOrder',
description: 'Look up an order by ID',
parameters: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'The order ID' },
},
required: ['orderId'],
},
handler: async ({ orderId }) => {
const order = await fetchOrder(orderId)
return { result: order }
},
},Tip: For most use cases, prefer adding skills on the ChatBotKit platform instead of hardcoding functions. Platform skills can be added, removed, and reconfigured without code changes.
Edit lib/auth-options.js to add GitHub, email, or other providers:
import GitHubProvider from 'next-auth/providers/github'
providers: [
GoogleProvider({ ... }),
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
],