name: add-sanity-chatbot description: Add an AI chatbot that operates on your Content Lake to an existing Next.js + Sanity project. Use when adding a chat assistant to a site that already has the Studio and a Next.js frontend. Covers dependency installation, API route setup, chat UI components, Studio plugin configuration, and system prompt design.
Add an AI Chatbot That Operates on Your Content
Add an AI chatbot to your existing Next.js + Sanity project. The chatbot connects to the Content Lake via the Sanity Context MCP server, giving the LLM structured, schema-aware access to your content. It can answer questions, run GROQ queries, and reason over your data, not just match keywords.
What this gives you:
- A chat widget in your Next.js app connected to an LLM
- Schema-aware content access: the agent understands your content model, not just text similarity
- Semantic search layered on top of structural GROQ queries against the Content Lake
- Client-side tools for page context and screenshots
Prerequisites
Before starting, confirm:
- Existing Next.js app (App Router) with a working frontend
- Existing Studio (v5.1.0+), either embedded or separate
- Sanity project credentials available
Gather these credentials:
| Credential | Where to get it |
|---|---|
| Sanity Project ID | Your sanity.config.ts or sanity.io/manage |
| Dataset name | Usually production. Check your sanity.config.ts |
| Sanity API read token | sanity.io/manage -> Project -> API -> Tokens |
| Anthropic API key | From console.anthropic.com (or other provider) |
Workflow
Step 1: Set Up Sanity Context in Studio
Install the plugin and create a Sanity Context document to scope what content the chatbot can access.
See references/studio-setup.md
Step 2: Install Dependencies in Your Next.js App
IMPORTANT: Do NOT guess package versions. AI SDK packages update frequently. Always check the versions below or run npm info <package> version.
npm install @ai-sdk/anthropic@^3.0.23 @ai-sdk/mcp@^1.0.13 @ai-sdk/react@^3.0.52 ai@^6.0.50 zod@^4.3.6
Optional dependencies for advanced features (page context capture, screenshots):
npm install turndown html2canvas-pro lucide-react
npm install -D @types/turndown
Version reference (from the working ecommerce example):
| Package | Version | Notes |
|---|---|---|
@ai-sdk/anthropic |
^3.0.23 | Anthropic provider for Vercel AI SDK |
@ai-sdk/mcp |
^1.0.13 | MCP client for tool discovery |
@ai-sdk/react |
^3.0.52 | React hooks (useChat) |
ai |
^6.0.50 | Core Vercel AI SDK |
zod |
^4.3.6 | Schema validation for tool inputs |
turndown |
^7.2.2 | HTML-to-markdown for page context |
html2canvas-pro |
^1.6.6 | Screenshot capture |
lucide-react |
^0.563.0 | Icons for chat UI |
Step 3: Set Up Environment Variables
Add to your .env.local:
# Sanity Configuration (you may already have these)
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
# Sanity API token with read access
SANITY_API_READ_TOKEN=your-read-token
# Sanity Context slug (optional, defaults to "default")
# SANITY_CONTEXT_SLUG=default
# LLM API key
ANTHROPIC_API_KEY=your-anthropic-key
The MCP URL is constructed automatically from your project ID, dataset, and the optional SANITY_CONTEXT_SLUG (defaults to default).
Step 4: Create the Chat Implementation
Create the API route and chat UI components.
See references/chat-implementation.md
Step 5: Test the Integration
- Start your dev server:
npm run dev - Open your app and interact with the chat widget
- The agent should call
initial_contextfirst to understand your content types - Try asking: "What content do you have access to?"
You can also test the API route directly:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "What content do you have access to?"}]}'
Step 6: Customize the System Prompt
The system prompt shapes how your chatbot behaves. Define it inline in the API route or store it in a Sanity document for easy editing.
Basic inline prompt:
const SYSTEM_PROMPT = `
You are a helpful assistant for this website.
## Your Capabilities
- Search and retrieve content using the available tools
- Answer questions about the site's content
- Help users find what they're looking for
## How to Respond
- Be concise and helpful
- When referencing content, include relevant details
- If you can't find what the user wants, suggest alternatives
## Tool Usage
- Use initial_context first to understand available content types
- Use groq_query to find specific content
- Use schema_explorer when you need field details
`;
For more prompt examples (e-commerce, docs, support), see the system prompts guide in the reference skill.
Step 7: Explore and Optimize (Recommended)
Once the chatbot works, explore your dataset and build a production-quality system prompt:
npx skills add https://github.com/sanity-io/context --skill optimize-agent-prompt
Important Notes
AI SDK v6: convertToModelMessages()
The Vercel AI SDK v6 requires converting UI messages to model messages before passing to streamText:
import {convertToModelMessages} from 'ai'
// In your API route:
messages: await convertToModelMessages(messages),
Do not pass raw UIMessage[] directly to streamText. This will cause type errors or silent failures.
Next 16 + Turbopack: next/dynamic Issues
If you are using Next.js 16 with Turbopack (the default dev bundler), you may encounter issues with next/dynamic for client components. If the chat component fails to render:
- Try importing it directly instead of using
next/dynamic - Or disable Turbopack:
next dev --no-turbopack - Check the Next.js GitHub issues for the latest status
MCP URL Format
The Sanity Context MCP server URL has two forms:
- Base URL (all content):
https://api.sanity.io/:apiVersion/context/mcp/:projectId/:dataset - Scoped URL (filtered content):
https://api.sanity.io/:apiVersion/context/mcp/:projectId/:dataset/:slug
Use the scoped URL for production. It limits what content the agent can access based on the GROQ filter in your Sanity Context document.
Available MCP Tools
| Tool | Purpose |
|---|---|
initial_context |
Get compressed schema overview (types, fields, document counts) |
groq_query |
Execute GROQ queries with optional semantic search |
schema_explorer |
Get detailed schema for a specific document type |
Troubleshooting
MCP connection fails
- Create a Sanity Context document in Studio and give it a slug
- If the slug is not
default, setSANITY_CONTEXT_SLUGin.env.local - Ensure the Studio is deployed (
npx sanity deploy)
"401 Unauthorized" from MCP
Your SANITY_API_READ_TOKEN is missing or invalid. Generate a new token at sanity.io/manage -> Project -> API -> Tokens with Viewer permissions.
"No documents found" / Empty results
Check your Sanity Context document's content filter:
- Is the GROQ filter correct?
- Are the document types spelled correctly?
- Are there published documents matching the filter?
Tools not appearing in LLM responses
- Log
mcpClient.tools()to verify tools are returned - Check the MCP URL (project ID, dataset, slug)
- Verify the Sanity Context document is published
The Sanity Context MCP server returns errors or no schema
The Sanity Context MCP server needs your schema deployed server-side. This happens automatically when Studio runs, but if it's not working:
- Ensure Studio is v5.1.0+
- Open your Studio in a browser (triggers schema deployment)
- Or manually deploy:
npx sanity schema deploy
Chat component not rendering
- Verify the component is marked
'use client' - Check browser console for hydration errors
- If using
next/dynamic, try direct import instead (see Turbopack note above)